├── Labs ├── Lab2 │ ├── Makefile │ ├── compile.sh │ ├── helloModule.c │ ├── test.c │ └── simple_char_driver.c ├── Lab4 │ ├── cfs.png │ ├── fifo.png │ ├── rr.png │ ├── Submission.zip │ ├── data │ │ ├── io-process_FIFO_LOW │ │ ├── io-process_RR_LOW │ │ ├── mixed_FIFO_LOW │ │ ├── mixed_RR_LOW │ │ ├── cpu-process_FIFO_MEDIUM │ │ ├── cpu-process_OTHER_LOW │ │ ├── cpu-process_RR_MEDIUM │ │ ├── io-process_RR_MEDIUM │ │ ├── mixed_FIFO_MEDIUM │ │ ├── mixed_RR_MEDIUM │ │ ├── io-process_FIFO_MEDIUM │ │ ├── io-process_OTHER_LOW │ │ ├── io-process_RR_HIGH │ │ ├── mixed_OTHER_LOW │ │ ├── cpu-process_FIFO_HIGH │ │ ├── cpu-process_OTHER_MEDIUM │ │ ├── cpu-process_RR_HIGH │ │ ├── io-process_FIFO_HIGH │ │ ├── io-process_OTHER_MEDIUM │ │ ├── mixed_FIFO_HIGH │ │ ├── mixed_OTHER_MEDIUM │ │ ├── mixed_RR_HIGH │ │ ├── io-process_OTHER_HIGH │ │ ├── cpu-process_OTHER_HIGH │ │ └── mixed_OTHER_HIGH │ ├── Makefile │ ├── testscript │ ├── README │ ├── rr_quantum.c │ ├── pi.c │ ├── Report.txt │ ├── pi-sched.c │ └── rw.c └── Lab5 │ ├── aes-crypt.h │ ├── copy of Makefile │ ├── Makefile │ ├── fusehello.c │ ├── aes-crypt-util.c │ ├── aes-crypt.c │ ├── README │ ├── xattr-util.c │ ├── fusexmp.c │ ├── pa5-encfs.c │ └── COPYING └── Problem Sets ├── Set4 └── prob3.jpg ├── Set5.md ├── Set4.md ├── Set1.md ├── Set3.md └── Set2.md /Labs/Lab2/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := helloModule.o 2 | obj-m += simple_char_driver.o 3 | -------------------------------------------------------------------------------- /Labs/Lab4/cfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jon5477/CSCI3753/HEAD/Labs/Lab4/cfs.png -------------------------------------------------------------------------------- /Labs/Lab4/fifo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jon5477/CSCI3753/HEAD/Labs/Lab4/fifo.png -------------------------------------------------------------------------------- /Labs/Lab4/rr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jon5477/CSCI3753/HEAD/Labs/Lab4/rr.png -------------------------------------------------------------------------------- /Labs/Lab2/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make -C /lib/modules/$(uname -r)/build M=$PWD modules 3 | -------------------------------------------------------------------------------- /Labs/Lab4/Submission.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jon5477/CSCI3753/HEAD/Labs/Lab4/Submission.zip -------------------------------------------------------------------------------- /Problem Sets/Set4/prob3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jon5477/CSCI3753/HEAD/Problem Sets/Set4/prob3.jpg -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_FIFO_LOW: -------------------------------------------------------------------------------- 1 | wall=0.11 user=0.00 system=0.03 CPU=36% i-switched=1 v-switched=3018 2 | wall=0.06 user=0.00 system=0.03 CPU=50% i-switched=1 v-switched=2015 3 | wall=0.11 user=0.00 system=0.03 CPU=35% i-switched=1 v-switched=3032 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_RR_LOW: -------------------------------------------------------------------------------- 1 | wall=0.09 user=0.00 system=0.03 CPU=38% i-switched=1 v-switched=2620 2 | wall=0.11 user=0.00 system=0.03 CPU=32% i-switched=0 v-switched=3038 3 | wall=0.10 user=0.00 system=0.03 CPU=35% i-switched=1 v-switched=2743 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_FIFO_LOW: -------------------------------------------------------------------------------- 1 | wall=0.28 user=0.40 system=0.02 CPU=151% i-switched=1 v-switched=2332 2 | wall=0.29 user=0.40 system=0.02 CPU=149% i-switched=1 v-switched=2483 3 | wall=0.29 user=0.41 system=0.03 CPU=150% i-switched=1 v-switched=2539 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_RR_LOW: -------------------------------------------------------------------------------- 1 | wall=0.32 user=0.42 system=0.02 CPU=139% i-switched=1 v-switched=3057 2 | wall=0.30 user=0.40 system=0.02 CPU=142% i-switched=1 v-switched=2938 3 | wall=0.32 user=0.40 system=0.02 CPU=130% i-switched=1 v-switched=2658 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_FIFO_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=1.83 user=3.63 system=0.01 CPU=199% i-switched=9 v-switched=106 2 | wall=1.91 user=3.62 system=0.01 CPU=190% i-switched=15 v-switched=106 3 | wall=1.94 user=3.68 system=0.01 CPU=190% i-switched=6 v-switched=106 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_OTHER_LOW: -------------------------------------------------------------------------------- 1 | wall=0.19 user=0.35 system=0.00 CPU=188% i-switched=127 v-switched=21 2 | wall=0.19 user=0.36 system=0.00 CPU=190% i-switched=135 v-switched=21 3 | wall=0.19 user=0.36 system=0.00 CPU=193% i-switched=123 v-switched=21 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_RR_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=1.94 user=3.68 system=0.01 CPU=190% i-switched=6 v-switched=106 2 | wall=1.98 user=3.75 system=0.02 CPU=190% i-switched=6 v-switched=106 3 | wall=1.99 user=3.78 system=0.01 CPU=190% i-switched=5 v-switched=106 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_RR_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=0.44 user=0.03 system=0.35 CPU=86% i-switched=4 v-switched=29376 2 | wall=0.43 user=0.03 system=0.34 CPU=86% i-switched=1 v-switched=30024 3 | wall=0.47 user=0.02 system=0.32 CPU=74% i-switched=1 v-switched=30039 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_FIFO_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=2.64 user=4.29 system=0.33 CPU=174% i-switched=7 v-switched=30419 2 | wall=2.48 user=3.99 system=0.30 CPU=172% i-switched=7 v-switched=30127 3 | wall=2.64 user=4.35 system=0.29 CPU=175% i-switched=3 v-switched=29553 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_RR_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=2.55 user=4.23 system=0.30 CPU=177% i-switched=5 v-switched=28894 2 | wall=2.45 user=4.03 system=0.32 CPU=177% i-switched=4 v-switched=29951 3 | wall=2.39 user=3.96 system=0.30 CPU=178% i-switched=2 v-switched=29839 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_FIFO_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=0.39 user=0.02 system=0.31 CPU=88% i-switched=4 v-switched=26794 2 | wall=0.41 user=0.03 system=0.32 CPU=84% i-switched=3 v-switched=28439 3 | wall=0.39 user=0.02 system=0.32 CPU=88% i-switched=4 v-switched=27584 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_OTHER_LOW: -------------------------------------------------------------------------------- 1 | wall=0.10 user=0.00 system=0.02 CPU=25% i-switched=148 v-switched=3785 2 | wall=0.11 user=0.00 system=0.02 CPU=26% i-switched=148 v-switched=3857 3 | wall=0.11 user=0.00 system=0.03 CPU=27% i-switched=99 v-switched=3787 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_RR_HIGH: -------------------------------------------------------------------------------- 1 | wall=3.92 user=0.36 system=3.70 CPU=103% i-switched=23 v-switched=237701 2 | wall=3.99 user=0.35 system=3.57 CPU=98% i-switched=22 v-switched=218246 3 | wall=3.92 user=0.36 system=3.79 CPU=105% i-switched=17 v-switched=290356 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_OTHER_LOW: -------------------------------------------------------------------------------- 1 | wall=0.33 user=0.40 system=0.04 CPU=135% i-switched=1092 v-switched=3386 2 | wall=0.32 user=0.41 system=0.03 CPU=138% i-switched=474 v-switched=3643 3 | wall=0.44 user=0.62 system=0.02 CPU=148% i-switched=376 v-switched=3866 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_FIFO_HIGH: -------------------------------------------------------------------------------- 1 | wall=20.63 user=39.22 system=0.17 CPU=190% i-switched=39 v-switched=1010 2 | wall=20.83 user=39.43 system=0.17 CPU=190% i-switched=40 v-switched=1006 3 | wall=20.22 user=38.34 system=0.16 CPU=190% i-switched=41 v-switched=1006 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_OTHER_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=1.84 user=3.59 system=0.01 CPU=195% i-switched=1169 v-switched=199 2 | wall=1.83 user=3.59 system=0.01 CPU=197% i-switched=1103 v-switched=200 3 | wall=1.84 user=3.62 system=0.02 CPU=197% i-switched=1137 v-switched=197 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_RR_HIGH: -------------------------------------------------------------------------------- 1 | wall=20.47 user=38.76 system=0.17 CPU=190% i-switched=44 v-switched=1013 2 | wall=20.59 user=39.08 system=0.17 CPU=190% i-switched=57 v-switched=1007 3 | wall=20.24 user=38.27 system=0.18 CPU=189% i-switched=44 v-switched=2330 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_FIFO_HIGH: -------------------------------------------------------------------------------- 1 | wall=3.59 user=0.36 system=3.71 CPU=113% i-switched=22 v-switched=232481 2 | wall=3.63 user=0.37 system=3.86 CPU=116% i-switched=30 v-switched=290520 3 | wall=3.70 user=0.36 system=3.88 CPU=114% i-switched=19 v-switched=303173 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_OTHER_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=0.40 user=0.02 system=0.23 CPU=63% i-switched=907 v-switched=33517 2 | wall=0.34 user=0.02 system=0.24 CPU=78% i-switched=812 v-switched=33723 3 | wall=0.34 user=0.02 system=0.25 CPU=83% i-switched=909 v-switched=33640 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_FIFO_HIGH: -------------------------------------------------------------------------------- 1 | wall=24.86 user=41.40 system=3.52 CPU=180% i-switched=80 v-switched=218766 2 | wall=24.72 user=40.82 system=3.60 CPU=179% i-switched=66 v-switched=307821 3 | wall=24.70 user=40.30 system=3.86 CPU=178% i-switched=78 v-switched=298674 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_OTHER_MEDIUM: -------------------------------------------------------------------------------- 1 | wall=2.62 user=4.38 system=0.37 CPU=181% i-switched=3530 v-switched=36004 2 | wall=2.37 user=4.04 system=0.27 CPU=181% i-switched=2665 v-switched=34061 3 | wall=2.38 user=4.05 system=0.24 CPU=180% i-switched=2271 v-switched=34070 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_RR_HIGH: -------------------------------------------------------------------------------- 1 | wall=24.31 user=40.30 system=3.79 CPU=181% i-switched=78 v-switched=295878 2 | wall=24.68 user=40.94 system=3.54 CPU=180% i-switched=89 v-switched=217338 3 | wall=24.65 user=40.65 system=3.80 CPU=180% i-switched=73 v-switched=210934 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/io-process_OTHER_HIGH: -------------------------------------------------------------------------------- 1 | wall=3.80 user=0.32 system=3.02 CPU=87% i-switched=5632 v-switched=406543 2 | wall=4.90 user=0.33 system=3.47 CPU=77% i-switched=8228 v-switched=395954 3 | wall=4.57 user=0.32 system=3.34 CPU=80% i-switched=6901 v-switched=410221 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/cpu-process_OTHER_HIGH: -------------------------------------------------------------------------------- 1 | wall=19.95 user=39.20 system=0.23 CPU=197% i-switched=11645 v-switched=1609 2 | wall=20.94 user=41.14 system=0.25 CPU=197% i-switched=12190 v-switched=1666 3 | wall=21.48 user=42.06 system=0.28 CPU=197% i-switched=12141 v-switched=1669 4 | -------------------------------------------------------------------------------- /Labs/Lab4/data/mixed_OTHER_HIGH: -------------------------------------------------------------------------------- 1 | wall=23.87 user=42.31 system=3.38 CPU=191% i-switched=45836 v-switched=346324 2 | wall=24.41 user=42.48 system=3.79 CPU=189% i-switched=41479 v-switched=358671 3 | wall=24.70 user=43.43 system=3.74 CPU=190% i-switched=40610 v-switched=354948 4 | -------------------------------------------------------------------------------- /Labs/Lab2/helloModule.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int hello_init(void) 5 | { 6 | printk(KERN_ALERT "inside %s function\n",__FUNCTION__); 7 | return 0; 8 | } 9 | 10 | int hello_exit(void) 11 | { 12 | printk(KERN_ALERT "inside %s function\n",__FUNCTION__); 13 | return 0; 14 | } 15 | 16 | module_init(hello_init); 17 | module_exit(hello_exit); 18 | -------------------------------------------------------------------------------- /Labs/Lab2/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define DEVICE "/dev/simple_character_device" 5 | #define BUFFER_SIZE 1024 6 | 7 | int main () { 8 | char command, buffer[BUFFER_SIZE]; 9 | int file = open(DEVICE, O_RDWR); 10 | while (1) { 11 | printf("\nr) Read from device\nw) Write to device\ne) Exit device\nAnything else to continue reading and writing\n\nEnter command: "); 12 | scanf("%c", &command); 13 | switch (command) { 14 | case 'w': 15 | case 'W': 16 | printf("Enter data you want to write to the device: "); 17 | scanf("%s", buffer); 18 | write(file, buffer, BUFFER_SIZE); 19 | while (getchar() != '\n'); 20 | break; 21 | case 'r': 22 | case 'R': 23 | read(file, buffer, BUFFER_SIZE); 24 | printf("Device output: %s\n", buffer); 25 | while (getchar() != '\n'); 26 | break; 27 | case 'e': 28 | case 'E': 29 | return 0; 30 | default: 31 | while (getchar() != '\n'); 32 | } 33 | } 34 | close(file); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /Labs/Lab4/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -c -g -Wall -Wextra 3 | LFLAGS = -g -Wall -Wextra 4 | 5 | INPUTFILESIZEMEGABYTES = 1 6 | 7 | KILO = 1024 8 | MEGA = $(shell echo $(KILO)\*$(KILO) | bc) 9 | INPUTFILESIZEBYTES = $(shell echo $(MEGA)\*$(INPUTFILESIZEMEGABYTES) | bc) 10 | INPUTBLOCKSIZEBYTES = $(KILO) 11 | INPUTBLOCKS = $(shell echo $(INPUTFILESIZEBYTES)\/$(INPUTBLOCKSIZEBYTES) | bc) 12 | 13 | .PHONY: all clean 14 | 15 | all: pi pi-sched rw rr_quantum 16 | 17 | pi: pi.o 18 | $(CC) $(LFLAGS) $^ -o $@ -lm 19 | 20 | pi-sched: pi-sched.o 21 | $(CC) $(LFLAGS) $^ -o $@ -lm 22 | 23 | rw: rw.o rwinput 24 | $(CC) $(LFLAGS) rw.o -o $@ -lm 25 | 26 | rr_quantum: rr_quantum.o 27 | $(CC) $(LFLAGS) $^ -o $@ -lm 28 | 29 | pi.o: pi.c 30 | $(CC) $(CFLAGS) $< 31 | 32 | pi-sched.o: pi-sched.c 33 | $(CC) $(CFLAGS) $< 34 | 35 | rw.o: rw.c 36 | $(CC) $(CFLAGS) $< 37 | 38 | rwinput: Makefile 39 | dd if=/dev/urandom of=./rwinput bs=$(INPUTBLOCKSIZEBYTES) count=$(INPUTBLOCKS) 40 | 41 | rr_quantum.o: rr_quantum.c 42 | $(CC) $(CFLAGS) $< 43 | 44 | clean: testclean 45 | rm -f pi pi-sched rw rr_quantum 46 | rm -f rwinput 47 | rm -f *.o 48 | rm -f *~ 49 | rm -f handout/*~ 50 | rm -f handout/*.log 51 | rm -f handout/*.aux 52 | 53 | testclean: 54 | rm -f rwoutput* 55 | -------------------------------------------------------------------------------- /Labs/Lab4/testscript: -------------------------------------------------------------------------------- 1 | #/!/bin/bash 2 | 3 | #File: testscript 4 | #Author: Andy Sayler 5 | #Project: CSCI 3753 Programming Assignment 3 6 | #Create Date: 2012/03/09 7 | #Modify Date: 2012/03/21 8 | #Description: 9 | # A simple bash script to run a signle copy of each test case 10 | # and gather the relevent data. 11 | 12 | ITERATIONS=100000000 13 | BYTESTOCOPY=102400 14 | BLOCKSIZE=1024 15 | TIMEFORMAT="wall=%e user=%U system=%S CPU=%P i-switched=%c v-switched=%w" 16 | MAKE="make -s" 17 | 18 | echo Building code... 19 | $MAKE clean 20 | $MAKE 21 | 22 | echo Starting test runs... 23 | 24 | echo Calculating pi over $ITERATIONS iterations using SCHED_OTHER with 1 simultaneous process... 25 | /usr/bin/time -f "$TIMEFORMAT" ./pi-sched $ITERATIONS SCHED_OTHER > /dev/null 26 | 27 | echo Calculating pi over $ITERATIONS iterations using SCHED_FIFO with 1 simultaneous process... 28 | /usr/bin/time -f "$TIMEFORMAT" sudo ./pi-sched $ITERATIONS SCHED_FIFO > /dev/null 29 | 30 | echo Calculating pi over $ITERATIONS iterations using SCHED_RR with 1 simultaneous process... 31 | /usr/bin/time -f "$TIMEFORMAT" sudo ./pi-sched $ITERATIONS SCHED_RR > /dev/null 32 | 33 | echo Copying $BYTESTOCOPY bytes in blocks of $BLOCKSIZE from rwinput to rwoutput 34 | echo using SCHED_OTHER with 1 simultaneous process... 35 | /usr/bin/time -f "$TIMEFORMAT" ./rw $BYTESTOCOPY $BLOCKSIZE > /dev/null 36 | -------------------------------------------------------------------------------- /Labs/Lab4/README: -------------------------------------------------------------------------------- 1 | CS3753 (Operating Systems) 2 | Spring 2012 3 | University of Colorado Boulder 4 | Programming Assignment 3 5 | Public Code 6 | 7 | By Andy Sayler - 2012 8 | http://www.andysayler.com 9 | 10 | With help from: 11 | Junho Ahn - 2012 12 | 13 | ---Folders--- 14 | handout - Assignment description and documentation 15 | 16 | ---Executables--- 17 | ./testscript - A simple bash script for running a few sample test cases 18 | ./pi - A simple program for statistically calculating pi 19 | ./pi-sched - A simple program for statistically calculating pi using 20 | a specific scheduling policy 21 | ./rw - A simple i/o bound example program. 22 | ./rr_quantum - A simple program for determing the RR quantum. 23 | 24 | ---Examples--- 25 | Build: 26 | make 27 | 28 | Clean: 29 | make clean 30 | 31 | pi: 32 | ./pi 33 | ./pi 34 | 35 | pi-sched: 36 | ./pi-sched 37 | ./pi-sched 38 | ./pi-sched 39 | 40 | rw: 41 | ./rw 42 | ./rw <#Bytes to Write to Output File> 43 | ./rw <#Bytes to Write to Output File> 44 | ./rw <#Bytes to Write to Output File> 45 | ./rw <#Bytes to Write to Output File> 46 | 47 | testscript: 48 | ./testscript 49 | 50 | rr_quantum: 51 | sudo ./rr_quantum 52 | -------------------------------------------------------------------------------- /Labs/Lab5/aes-crypt.h: -------------------------------------------------------------------------------- 1 | /* aes-crypt.h 2 | * High level function interface for performing AES encryption on FILE pointers 3 | * Uses OpenSSL libcrypto EVP API 4 | * 5 | * By Andy Sayler (www.andysayler.com) 6 | * Created 04/17/12 7 | * Modified 04/18/12 8 | * 9 | * Derived from OpenSSL.org EVP_Encrypt_* Manpage Examples 10 | * http://www.openssl.org/docs/crypto/EVP_EncryptInit.html#EXAMPLES 11 | * 12 | * With additional information from Saju Pillai's OpenSSL AES Example 13 | * http://saju.net.in/blog/?p=36 14 | * http://saju.net.in/code/misc/openssl_aes.c.txt 15 | * 16 | */ 17 | 18 | #ifndef AES_CRYPT_H 19 | #define AES_CRYPT_H 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #define BLOCKSIZE 1024 29 | #define FAILURE 0 30 | #define SUCCESS 1 31 | 32 | /* int do_crypt(FILE* in, FILE* out, int action, char* key_str) 33 | * Purpose: Perform cipher on in File* and place result in out File* 34 | * Args: FILE* in : Input File Pointer 35 | * FILE* out : Output File Pointer 36 | * int action : Cipher action (1=encrypt, 0=decrypt, -1=pass-through (copy)) 37 | * char* key_str : C-string containing passpharse from which key is derived 38 | * Return: FAILURE on error, SUCCESS on success 39 | */ 40 | extern int do_crypt(FILE* in, FILE* out, int action, char* key_str); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Labs/Lab4/rr_quantum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: rr_quantum.c 3 | * Author: Andy Sayler 4 | * Project: CSCI 3753 Programming Assignment 3 5 | * Create Date: 2012/03/22 6 | * Modify Date: 2012/03/22 7 | * Description: Prints the RR quantum for a given system. 8 | */ 9 | 10 | /* Library Includes */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define NANO 1000000000.0 20 | 21 | int main(int argc, char* argv[]){ 22 | 23 | (void) argc; 24 | (void) argv; 25 | 26 | struct sched_param param; 27 | int policy; 28 | struct timespec tp; 29 | double qs = 0.0; 30 | 31 | /* Set Policy */ 32 | policy = SCHED_RR; 33 | 34 | /* Set process to max prioty for given scheduler */ 35 | param.sched_priority = sched_get_priority_max(policy); 36 | 37 | /* Set new scheduler policy */ 38 | fprintf(stdout, "Current Scheduling Policy: %d\n", sched_getscheduler(0)); 39 | fprintf(stdout, "Setting Scheduling Policy to: %d\n", policy); 40 | if(sched_setscheduler(0, policy, ¶m)){ 41 | perror("Error setting scheduler policy"); 42 | exit(EXIT_FAILURE); 43 | } 44 | fprintf(stdout, "New Scheduling Policy: %d\n", sched_getscheduler(0)); 45 | 46 | /* Find RR Quantum */ 47 | if(sched_rr_get_interval(getpid(), &tp)){ 48 | perror("Error getting RR Quantum"); 49 | exit(EXIT_FAILURE); 50 | } 51 | 52 | fprintf(stdout, "tp.tv_sec = %ld\n", tp.tv_sec); 53 | fprintf(stdout, "tp.tv_nsec = %ld\n", tp.tv_nsec); 54 | qs = (tp.tv_nsec / NANO) + tp.tv_sec; 55 | fprintf(stdout, "RR Quantum = %f seconds\n", qs); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Labs/Lab4/pi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: pi.c 3 | * Author: Andy Sayler 4 | * Project: CSCI 3753 Programming Assignment 3 5 | * Create Date: 2012/03/07 6 | * Modify Date: 2012/03/09 7 | * Description: 8 | * This file contains a simple program for statistically 9 | * calculating pi. 10 | */ 11 | 12 | /* Local Includes */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* Local Defines */ 19 | #define DEFAULT_ITERATIONS 1000000 20 | #define RADIUS (RAND_MAX / 2) 21 | 22 | /* Local Functions */ 23 | inline double dist(double x0, double y0, double x1, double y1){ 24 | return sqrt(pow((x1-x0),2) + pow((y1-y0),2)); 25 | } 26 | 27 | inline double zeroDist(double x, double y){ 28 | return dist(0, 0, x, y); 29 | } 30 | 31 | int main(int argc, char* argv[]){ 32 | 33 | long i; 34 | long iterations; 35 | double x, y; 36 | double inCircle = 0.0; 37 | double inSquare = 0.0; 38 | double pCircle = 0.0; 39 | double piCalc = 0.0; 40 | 41 | /* Process program arguments to select iterations */ 42 | /* Set default iterations if not supplied */ 43 | if(argc < 2){ 44 | iterations = DEFAULT_ITERATIONS; 45 | } 46 | /* Set iterations if supplied */ 47 | else{ 48 | iterations = atol(argv[1]); 49 | if(iterations < 1){ 50 | fprintf(stderr, "Bad iterations value\n"); 51 | exit(EXIT_FAILURE); 52 | } 53 | } 54 | 55 | /* Calculate pi using statistical methode across all iterations*/ 56 | for(i=0; i 3 | # Adopted from work by: Chris Wailes 4 | # Project: CSCI 3753 Programming Assignment 5 5 | # Creation Date: 2010/04/06 6 | # Modififed Date: 2012/04/12 7 | # Description: 8 | # This is the Makefile for PA5. 9 | 10 | 11 | CC = gcc 12 | 13 | CFLAGSFUSE = `pkg-config fuse --cflags` 14 | LLIBSFUSE = `pkg-config fuse --libs` 15 | LLIBSOPENSSL = -lcrypto 16 | 17 | CFLAGS = -c -g -Wall -Wextra 18 | LFLAGS = -g -Wall -Wextra 19 | 20 | FUSE_EXAMPLES = fusehello fusexmp pa5-encfs 21 | XATTR_EXAMPLES = xattr-util 22 | OPENSSL_EXAMPLES = aes-crypt-util 23 | 24 | .PHONY: all fuse-examples xattr-examples openssl-examples clean 25 | 26 | all: fuse-examples xattr-examples openssl-examples 27 | 28 | fuse-examples: $(FUSE_EXAMPLES) 29 | xattr-examples: $(XATTR_EXAMPLES) 30 | openssl-examples: $(OPENSSL_EXAMPLES) 31 | 32 | fusehello: fusehello.o 33 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) 34 | 35 | fusexmp: fusexmp.o 36 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) 37 | 38 | pa5-encfs: pa5-encfs.o 39 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) 40 | 41 | xattr-util: xattr-util.o 42 | $(CC) $(LFLAGS) $^ -o $@ 43 | 44 | aes-crypt-util: aes-crypt-util.o aes-crypt.o 45 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSOPENSSL) 46 | 47 | fusehello.o: fusehello.c 48 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 49 | 50 | fusexmp.o: fusexmp.c 51 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 52 | 53 | pa5-encfs.o: pa5-encfs.c 54 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 55 | 56 | xattr-util.o: xattr-util.c 57 | $(CC) $(CFLAGS) $< 58 | 59 | aes-crypt-util.o: aes-crypt-util.c aes-crypt.h 60 | $(CC) $(CFLAGS) $< 61 | 62 | aes-crypt.o: aes-crypt.c aes-crypt.h 63 | $(CC) $(CFLAGS) $< 64 | 65 | clean: 66 | rm -f $(FUSE_EXAMPLES) 67 | rm -f $(XATTR_EXAMPLES) 68 | rm -f $(OPENSSL_EXAMPLES) 69 | rm -f *.o 70 | rm -f *~ 71 | rm -f handout/*~ 72 | rm -f handout/*.log 73 | rm -f handout/*.aux 74 | rm -f handout/*.out 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Labs/Lab5/Makefile: -------------------------------------------------------------------------------- 1 | # File: Makefile 2 | # By: Andy Sayler 3 | # Adopted from work by: Chris Wailes 4 | # Project: CSCI 3753 Programming Assignment 5 5 | # Creation Date: 2010/04/06 6 | # Modififed Date: 2012/04/12 7 | # Description: 8 | # This is the Makefile for PA5. 9 | 10 | 11 | CC = gcc 12 | 13 | CFLAGSFUSE = `pkg-config fuse --cflags` 14 | LLIBSFUSE = `pkg-config fuse --libs` 15 | LLIBSOPENSSL = -lcrypto 16 | 17 | CFLAGS = -c -g -Wall -Wextra 18 | LFLAGS = -g -Wall -Wextra 19 | 20 | FUSE_EXAMPLES = fusehello fusexmp pa5-encfs 21 | XATTR_EXAMPLES = xattr-util 22 | OPENSSL_EXAMPLES = aes-crypt-util 23 | 24 | .PHONY: all fuse-examples xattr-examples openssl-examples clean 25 | 26 | all: fuse-examples xattr-examples openssl-examples 27 | 28 | fuse-examples: $(FUSE_EXAMPLES) 29 | xattr-examples: $(XATTR_EXAMPLES) 30 | openssl-examples: $(OPENSSL_EXAMPLES) 31 | 32 | fusehello: fusehello.o 33 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) 34 | 35 | fusexmp: fusexmp.o 36 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) 37 | 38 | pa5-encfs: pa5-encfs.o aes-crypt.o 39 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSFUSE) $(LLIBSOPENSSL) 40 | 41 | xattr-util: xattr-util.o 42 | $(CC) $(LFLAGS) $^ -o $@ 43 | 44 | aes-crypt-util: aes-crypt-util.o aes-crypt.o 45 | $(CC) $(LFLAGS) $^ -o $@ $(LLIBSOPENSSL) 46 | 47 | fusehello.o: fusehello.c 48 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 49 | 50 | fusexmp.o: fusexmp.c 51 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 52 | 53 | pa5-encfs.o: pa5-encfs.c 54 | $(CC) $(CFLAGS) $(CFLAGSFUSE) $< 55 | 56 | xattr-util.o: xattr-util.c 57 | $(CC) $(CFLAGS) $< 58 | 59 | aes-crypt-util.o: aes-crypt-util.c aes-crypt.h 60 | $(CC) $(CFLAGS) $< 61 | 62 | aes-crypt.o: aes-crypt.c aes-crypt.h 63 | $(CC) $(CFLAGS) $< 64 | 65 | clean: 66 | rm -f $(FUSE_EXAMPLES) 67 | rm -f $(XATTR_EXAMPLES) 68 | rm -f $(OPENSSL_EXAMPLES) 69 | rm -f *.o 70 | rm -f *~ 71 | rm -f handout/*~ 72 | rm -f handout/*.log 73 | rm -f handout/*.aux 74 | rm -f handout/*.out 75 | -------------------------------------------------------------------------------- /Labs/Lab5/fusehello.c: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | Minor modifications and note by Andy Sayler (2012) 6 | 7 | Source: fuse-2.8.7.tar.gz examples directory 8 | http://sourceforge.net/projects/fuse/files/fuse-2.X/ 9 | 10 | See FUSE wiki for details: 11 | http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Hello_World 12 | 13 | This program can be distributed under the terms of the GNU GPL. 14 | See the file COPYING. 15 | 16 | gcc -Wall `pkg-config fuse --cflags` hello.c -o hello `pkg-config fuse --libs` 17 | */ 18 | 19 | #define FUSE_USE_VERSION 28 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | static const char *hello_str = "Hello World!\n"; 28 | static const char *hello_path = "/hello"; 29 | 30 | static int hello_getattr(const char *path, struct stat *stbuf) 31 | { 32 | int res = 0; 33 | 34 | memset(stbuf, 0, sizeof(struct stat)); 35 | if (strcmp(path, "/") == 0) { 36 | stbuf->st_mode = S_IFDIR | 0755; 37 | stbuf->st_nlink = 2; 38 | } else if (strcmp(path, hello_path) == 0) { 39 | stbuf->st_mode = S_IFREG | 0444; 40 | stbuf->st_nlink = 1; 41 | stbuf->st_size = strlen(hello_str); 42 | } else 43 | res = -ENOENT; 44 | 45 | return res; 46 | } 47 | 48 | static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 49 | off_t offset, struct fuse_file_info *fi) 50 | { 51 | (void) offset; 52 | (void) fi; 53 | 54 | if (strcmp(path, "/") != 0) 55 | return -ENOENT; 56 | 57 | filler(buf, ".", NULL, 0); 58 | filler(buf, "..", NULL, 0); 59 | filler(buf, hello_path + 1, NULL, 0); 60 | 61 | return 0; 62 | } 63 | 64 | static int hello_open(const char *path, struct fuse_file_info *fi) 65 | { 66 | if (strcmp(path, hello_path) != 0) 67 | return -ENOENT; 68 | 69 | if ((fi->flags & 3) != O_RDONLY) 70 | return -EACCES; 71 | 72 | return 0; 73 | } 74 | 75 | static int hello_read(const char *path, char *buf, size_t size, off_t offset, 76 | struct fuse_file_info *fi) 77 | { 78 | size_t len; 79 | (void) fi; 80 | if(strcmp(path, hello_path) != 0) 81 | return -ENOENT; 82 | 83 | len = strlen(hello_str); 84 | if (offset < (int)len) { 85 | if (offset + size > len) 86 | size = len - offset; 87 | memcpy(buf, hello_str + offset, size); 88 | } else 89 | size = 0; 90 | 91 | return size; 92 | } 93 | 94 | static struct fuse_operations hello_oper = { 95 | .getattr = hello_getattr, 96 | .readdir = hello_readdir, 97 | .open = hello_open, 98 | .read = hello_read, 99 | }; 100 | 101 | int main(int argc, char *argv[]) 102 | { 103 | return fuse_main(argc, argv, &hello_oper, NULL); 104 | } 105 | -------------------------------------------------------------------------------- /Labs/Lab5/aes-crypt-util.c: -------------------------------------------------------------------------------- 1 | /* aes-crypt.c 2 | * AES encryption demo program using OpenSSL EVP API via local aes-crypt library 3 | * 4 | * See aes-crypt.h and aes-crypt.c for more details 5 | * 6 | * By Andy Sayler (www.andysayler.com) 7 | * Created 04/17/12 8 | * Modified 04/18/12 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "aes-crypt.h" 17 | 18 | int main(int argc, char **argv) 19 | { 20 | 21 | /* Local vars */ 22 | int action = 0; 23 | int ifarg; 24 | int ofarg; 25 | FILE* inFile = NULL; 26 | FILE* outFile = NULL; 27 | char* key_str = NULL; 28 | 29 | /* Check General Input */ 30 | if(argc < 3){ 31 | fprintf(stderr, "usage: %s %s\n", argv[0], 32 | " "); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | /* Encrypt Case */ 37 | if(!strcmp(argv[1], "-e")){ 38 | /* Check Args */ 39 | if(argc != 5){ 40 | fprintf(stderr, "usage: %s %s\n", argv[0], 41 | "-e "); 42 | exit(EXIT_FAILURE); 43 | } 44 | /* Set Vars */ 45 | key_str = argv[2]; 46 | ifarg = 3; 47 | ofarg = 4; 48 | action = 1; 49 | } 50 | /* Decrypt Case */ 51 | else if(!strcmp(argv[1], "-d")){ 52 | /* Check Args */ 53 | if(argc != 5){ 54 | fprintf(stderr, "usage: %s %s\n", argv[0], 55 | "-d "); 56 | exit(EXIT_FAILURE); 57 | } 58 | /* Set Vars */ 59 | key_str = argv[2]; 60 | ifarg = 3; 61 | ofarg = 4; 62 | action = 0; 63 | } 64 | /* Pass-Through (Copy) Case */ 65 | else if(!strcmp(argv[1], "-c")){ 66 | /* Check Args */ 67 | if(argc != 4){ 68 | fprintf(stderr, "usage: %s %s\n", argv[0], 69 | "-c "); 70 | exit(EXIT_FAILURE); 71 | } 72 | /* Set Vars */ 73 | key_str = NULL; 74 | ifarg = 2; 75 | ofarg = 3; 76 | action = -1; 77 | } 78 | /* Bad Case */ 79 | else { 80 | fprintf(stderr, "Unkown action\n"); 81 | exit(EXIT_FAILURE); 82 | } 83 | 84 | /* Open Files */ 85 | inFile = fopen(argv[ifarg], "rb"); 86 | if(!inFile){ 87 | perror("infile fopen error"); 88 | return EXIT_FAILURE; 89 | } 90 | outFile = fopen(argv[ofarg], "wb+"); 91 | if(!outFile){ 92 | perror("outfile fopen error"); 93 | return EXIT_FAILURE; 94 | } 95 | 96 | /* Perform do_crpt action (encrypt, decrypt, copy) */ 97 | if(!do_crypt(inFile, outFile, action, key_str)){ 98 | fprintf(stderr, "do_crypt failed\n"); 99 | } 100 | 101 | /* Cleanup */ 102 | if(fclose(outFile)){ 103 | perror("outFile fclose error\n"); 104 | } 105 | if(fclose(inFile)){ 106 | perror("inFile fclose error\n"); 107 | } 108 | 109 | return EXIT_SUCCESS; 110 | } 111 | -------------------------------------------------------------------------------- /Labs/Lab4/Report.txt: -------------------------------------------------------------------------------- 1 | Abstract 2 | 3 | Through extensive testing of the Linux task scheduler, the running time data results determined some interesting details of the individual scheduling policies to maximize work done in less time for each respective task (CPU bound, IO bound, mixed) based on number of processes created. Overall, based on the results there was no respective "winning" scheduling algorithm based on running time since most the running time of each respective algorithm was generally the same for each task. However, the main difference in the different running algorithms would be the number of context switches for each algorithm. 4 | 5 | Introduction 6 | 7 | For this benchmarking test, we tested different conditions for each running program based on number of running processes. The number of running processes were split into 3 categories: low for 5 simultaneous running processes, medium for 70 simultaneous running processes, and high for 300 simultaneous running processes. 8 | 9 | Method 10 | 11 | For our CPU bound task, we used the included pi-scheduler to run our scheduling benchmark tests. 12 | 13 | For our IO bound task, we used the included file read/writing program to run our scheduling benchmark tests. 14 | 15 | For our mixed task, we used both the pi-scheduler and read/writing program for the scheduling benchmark tests. 16 | 17 | Results 18 | 19 | [The graphs are located in the same directory as this report as images.] 20 | 21 | Analysis 22 | 23 | Initially I expected either CFS to have the highest overhead because of the execution order of tasks. For example, if a long-running task is currently enqueued and many new tasks arrive, that adds some additional overhead to the running task since it may trigger a context switch as more tasks arrive. I expected quite a bit of context switching for higher simultaneous running processes and found this to be the case. What had surprised me was the number of context switches in the FIFO scheduling queue, I considered the context switches in the FIFO to be higher than what the results had given. Based on the results, the higher simultaneous processes all had the similar running time. I would not consider this particularly surprising since all the running processes had a generally uniform running time (they were all executing the same program and doing the same thing). In consideration for the different types of tasks, it was not surprising to see that there were more interrupts (both voluntary and involuntary) for IO bound tasks since IO bound tasks are considerably slower than CPU bound tasks. 24 | 25 | Conclusion 26 | 27 | Based on our running results, I can see why CFS is used as the default task scheduler for Linux. Since it is essentially a culmination of CFS and RR, each program gets an appropriate amount of time to run on the CPU and if it uses too much CPU time then the scheduler will interrupt the process and schedule another process. This is good for fault isolation and preventing CPU starvation. 28 | 29 | References 30 | 31 | This programming assignment was performed in conjunction with Yu Zhou. The benchmarking was performed on his machine. -------------------------------------------------------------------------------- /Labs/Lab4/pi-sched.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: pi-sched.c 3 | * Author: Andy Sayler 4 | * Project: CSCI 3753 Programming Assignment 3 5 | * Create Date: 2012/03/07 6 | * Modify Date: 2012/03/09 7 | * Description: 8 | * This file contains a simple program for statistically 9 | * calculating pi using a specific scheduling policy. 10 | */ 11 | 12 | /* Local Includes */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define DEFAULT_ITERATIONS 1000000 21 | #define RADIUS (RAND_MAX / 2) 22 | 23 | inline double dist(double x0, double y0, double x1, double y1){ 24 | return sqrt(pow((x1-x0),2) + pow((y1-y0),2)); 25 | } 26 | 27 | inline double zeroDist(double x, double y){ 28 | return dist(0, 0, x, y); 29 | } 30 | 31 | int main(int argc, char* argv[]){ 32 | 33 | long i; 34 | long iterations; 35 | struct sched_param param; 36 | int policy; 37 | double x, y; 38 | double inCircle = 0.0; 39 | double inSquare = 0.0; 40 | double pCircle = 0.0; 41 | double piCalc = 0.0; 42 | 43 | /* Process program arguments to select iterations and policy */ 44 | /* Set default iterations if not supplied */ 45 | if(argc < 2){ 46 | iterations = DEFAULT_ITERATIONS; 47 | } 48 | /* Set default policy if not supplied */ 49 | if(argc < 3){ 50 | policy = SCHED_OTHER; 51 | } 52 | /* Set iterations if supplied */ 53 | if(argc > 1){ 54 | iterations = atol(argv[1]); 55 | if(iterations < 1){ 56 | fprintf(stderr, "Bad iterations value\n"); 57 | exit(EXIT_FAILURE); 58 | } 59 | } 60 | /* Set policy if supplied */ 61 | if(argc > 2){ 62 | if(!strcmp(argv[2], "SCHED_OTHER")){ 63 | policy = SCHED_OTHER; 64 | } 65 | else if(!strcmp(argv[2], "SCHED_FIFO")){ 66 | policy = SCHED_FIFO; 67 | } 68 | else if(!strcmp(argv[2], "SCHED_RR")){ 69 | policy = SCHED_RR; 70 | } 71 | else{ 72 | fprintf(stderr, "Unhandeled scheduling policy\n"); 73 | exit(EXIT_FAILURE); 74 | } 75 | } 76 | 77 | /* Set process to max prioty for given scheduler */ 78 | param.sched_priority = sched_get_priority_max(policy); 79 | 80 | /* Set new scheduler policy */ 81 | fprintf(stdout, "Current Scheduling Policy: %d\n", sched_getscheduler(0)); 82 | fprintf(stdout, "Setting Scheduling Policy to: %d\n", policy); 83 | if(sched_setscheduler(0, policy, ¶m)){ 84 | perror("Error setting scheduler policy"); 85 | exit(EXIT_FAILURE); 86 | } 87 | fprintf(stdout, "New Scheduling Policy: %d\n", sched_getscheduler(0)); 88 | 89 | /* Calculate pi using statistical methode across all iterations*/ 90 | for(i=0; i= 0){ 46 | if(!key_str){ 47 | /* Error */ 48 | fprintf(stderr, "Key_str must not be NULL\n"); 49 | return 0; 50 | } 51 | /* Build Key from String */ 52 | i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, 53 | (unsigned char*)key_str, strlen(key_str), nrounds, key, iv); 54 | if (i != 32) { 55 | /* Error */ 56 | fprintf(stderr, "Key size is %d bits - should be 256 bits\n", i*8); 57 | return 0; 58 | } 59 | /* Init Engine */ 60 | EVP_CIPHER_CTX_init(&ctx); 61 | EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv, action); 62 | } 63 | 64 | /* Loop through Input File*/ 65 | for(;;){ 66 | /* Read Block */ 67 | inlen = fread(inbuf, sizeof(*inbuf), BLOCKSIZE, in); 68 | if(inlen <= 0){ 69 | /* EOF -> Break Loop */ 70 | break; 71 | } 72 | 73 | /* If in cipher mode, perform cipher transform on block */ 74 | if(action >= 0){ 75 | if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) 76 | { 77 | /* Error */ 78 | EVP_CIPHER_CTX_cleanup(&ctx); 79 | return 0; 80 | } 81 | } 82 | /* If in pass-through mode. copy block as is */ 83 | else{ 84 | memcpy(outbuf, inbuf, inlen); 85 | outlen = inlen; 86 | } 87 | 88 | /* Write Block */ 89 | writelen = fwrite(outbuf, sizeof(*outbuf), outlen, out); 90 | if(writelen != outlen){ 91 | /* Error */ 92 | perror("fwrite error"); 93 | EVP_CIPHER_CTX_cleanup(&ctx); 94 | return 0; 95 | } 96 | } 97 | 98 | /* If in cipher mode, handle necessary padding */ 99 | if(action >= 0){ 100 | /* Handle remaining cipher block + padding */ 101 | if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) 102 | { 103 | /* Error */ 104 | EVP_CIPHER_CTX_cleanup(&ctx); 105 | return 0; 106 | } 107 | /* Write remainign cipher block + padding*/ 108 | fwrite(outbuf, sizeof(*inbuf), outlen, out); 109 | EVP_CIPHER_CTX_cleanup(&ctx); 110 | } 111 | 112 | /* Success */ 113 | return 1; 114 | } 115 | -------------------------------------------------------------------------------- /Labs/Lab2/simple_char_driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #define BUFFER_SIZE 1024 7 | #define MAJOR_NUMBER 547 8 | #define DEV_NAME "simple_character_device" 9 | 10 | static char device_buffer[BUFFER_SIZE]; 11 | static int openCount = 0; 12 | static int closeCount = 0; 13 | 14 | ssize_t simple_char_driver_read (struct file *pfile, char __user *buffer, size_t length, loff_t *offset) 15 | { 16 | /* *buffer is the userspace buffer to where you are writing the data you want to be read from the device file*/ 17 | /* length is the length of the userspace buffer*/ 18 | /* current position of the opened file*/ 19 | /* copy_to_user function. source is device_buffer (the buffer defined at the start of the code) and destination is the userspace buffer *buffer */ 20 | printk(KERN_ALERT "Reading from device.\n"); 21 | copy_to_user(buffer, device_buffer, length); 22 | return 0; 23 | } 24 | 25 | 26 | 27 | ssize_t simple_char_driver_write (struct file *pfile, const char __user *buffer, size_t length, loff_t *offset) 28 | { 29 | /* *buffer is the userspace buffer where you are writing the data you want to be written in the device file*/ 30 | /* length is the length of the userspace buffer*/ 31 | /* current position of the opened file*/ 32 | /* copy_from_user function. destination is device_buffer (the buffer defined at the start of the code) and source is the userspace buffer *buffer */ 33 | printk(KERN_ALERT "Writing to device.\n"); 34 | copy_from_user(device_buffer, buffer, length); 35 | printk(KERN_ALERT "Wrote %d bytes to device.\n", length); 36 | return length; 37 | } 38 | 39 | 40 | int simple_char_driver_open (struct inode *pinode, struct file *pfile) 41 | { 42 | /* print to the log file that the device is opened and also print the number of times this device has been opened until now*/ 43 | openCount++; 44 | printk(KERN_ALERT "Opened Device. Count: %d\n", openCount); 45 | return 0; 46 | } 47 | 48 | 49 | int simple_char_driver_close (struct inode *pinode, struct file *pfile) 50 | { 51 | /* print to the log file that the device is closed and also print the number of times this device has been closed until now*/ 52 | closeCount++; 53 | printk(KERN_ALERT "Closed Device. Count: %d\n", closeCount); 54 | return 0; 55 | } 56 | 57 | struct file_operations simple_char_driver_file_operations = { 58 | 59 | .owner = THIS_MODULE, 60 | /* add the function pointers to point to the corresponding file operations. look at the file fs.h in the linux souce code*/ 61 | .read = simple_char_driver_read, 62 | .write = simple_char_driver_write, 63 | .open = simple_char_driver_open, 64 | .release = simple_char_driver_close, 65 | }; 66 | 67 | static int simple_char_driver_init(void) 68 | { 69 | /* print to the log file that the init function is called.*/ 70 | /* register the device */ 71 | printk(KERN_ALERT "Initializing device.\n"); 72 | register_chrdev(MAJOR_NUMBER, DEV_NAME, &simple_char_driver_file_operations); 73 | return 0; 74 | } 75 | 76 | static int simple_char_driver_exit(void) 77 | { 78 | /* print to the log file that the exit function is called.*/ 79 | /* unregister the device using the register_chrdev() function. */ 80 | printk(KERN_ALERT "Removing device.\n"); 81 | unregister_chrdev(MAJOR_NUMBER, DEV_NAME); 82 | return 0; 83 | } 84 | 85 | /* add module_init and module_exit to point to the corresponding init and exit function*/ 86 | module_init(simple_char_driver_init); 87 | module_exit(simple_char_driver_exit); 88 | -------------------------------------------------------------------------------- /Labs/Lab5/README: -------------------------------------------------------------------------------- 1 | CS3753 (Operating Systems) 2 | Spring 2012 3 | University of Colorado Boulder 4 | Programming Assignment 5 5 | A FUSE Encrypted File System 6 | Public Code 7 | 8 | By Andy Sayler - 2012 9 | 10 | 11 | Inspired by work from Chris Wailes - 2010 12 | 13 | 14 | With help from: 15 | Junho Ahn - 2012 16 | 17 | Various files adopted from other exiting work. 18 | See file comments for specific details and references. 19 | 20 | ---Dependencies--- 21 | fuse-utils 22 | openssl 23 | attr 24 | attr-dev 25 | libfuse-dev 26 | libssl1.0.0 or libssl0.9.8 27 | libssl-dev 28 | 29 | Note: To use extended attributes (xattr) on EXT filesystems, 30 | you must add the 'user_xattr' mount option to the 31 | mount options of any mounts on which you intend to use 32 | extended attributes. Failure to so may result in an error 33 | when trying to set, get, or remove xattr values. 34 | 35 | ---Folders--- 36 | handout - Assignment description and documentation 37 | 38 | ---Files--- 39 | Makefile - GNU makefile to build all relevant code 40 | README - This file 41 | fusehello.c - Basic "Hello World" FUSE example 42 | fusexmp.c - Basic FUSE mirrored filesystem example (mirrors /) 43 | xattr-util.c - Basic Extended Attribute manipulation program 44 | aes-crypt-util.c - Basic AES encryption program using aes-crypt library 45 | aes-crypt.h - Basic AES file encryption library interface 46 | aes-crypt.c - Basic AES file encryption library implementation 47 | 48 | ---Executables--- 49 | fusehello - Mounting executable for "Hello World" FUSE filesystem example 50 | fusexmp - Mounting executable for root (\) mirror FUSE filesystem example 51 | xattr-util - A simple program for manipulating extended attributes 52 | aes-crypt-util - A simple program for encrypting, decrypting, or copying files 53 | 54 | ---Documentation--- 55 | handout/pa5.pdf - Assignment Instructions and Tips 56 | http://youtu.be/VrMi6RaUNDs - Assignment Explanation Video 1 57 | 58 | ---Examples--- 59 | 60 | ***Building*** 61 | 62 | Build All: 63 | make 64 | 65 | Build Fuse Examples and Utilities: 66 | make fuse-examples 67 | 68 | Build xattr Examples and Utilities: 69 | make xattr-examples 70 | 71 | Build OpenSSL/AES Examples and Utilities: 72 | make openssl-examples 73 | 74 | Clean: 75 | make clean 76 | 77 | ***FUSE Examples*** 78 | 79 | Mount fusehello on new directory 80 | mkdir 81 | ./fusehello 82 | 83 | Mount fusehello in Debug Mode on existing empty directory 84 | ./fusehello -d 85 | 86 | Mount fusexmp on existing directory and list (ls) mirrored root directory (/) 87 | ./fusexmp 88 | ls 89 | 90 | Unmount a FUSE filesystem 91 | fusermount -u 92 | 93 | ***OpenSSL Examples*** 94 | 95 | Copy FileA to FileB: 96 | ./aes-crypt-util -c 97 | 98 | Encrypt FileA to FileB using Passphrase: 99 | ./aes-crypt-util -e 100 | 101 | Decrypt FileA to FileB using Passphrase: 102 | (Note: error if FileA not encrypted with aes-crypt.h or if passphrase is wrong) 103 | ./aes-crypt-util -d 104 | 105 | ***xattr Examples*** 106 | 107 | List attributes set on a file 108 | ./xattr-util -l 109 | 110 | Set/Write attribute on a file 111 | ./xattr-util -s 112 | 113 | Get/Read attribute from a file 114 | ./xattr-util -g 115 | 116 | Remove attribute from a file 117 | ./xattr-util -r 118 | -------------------------------------------------------------------------------- /Problem Sets/Set5.md: -------------------------------------------------------------------------------- 1 | 1. You are asked to allocate a file according to either a File 2 | Allocation Table (FAT) or multi-level indexed allocation (UNIX 3 | inode - triply indirect). Assume that the file is 2000 disk 4 | blocks long, there are 4 KB per disk block, each pointer in the 5 | FAT occupies 4 bytes, the first index block contains 15 entries 6 | (of which 12 are direct, and one each is singly indirect, doubly 7 | indirect, and triply indirect - see slides or textbook), every 8 | other index block contains 15 entries (may be indirect depending 9 | on the nesting level), each index block entry takes 4 bytes, and 10 | unused index blocks don't count in the total memory cost, though 11 | unusued entries in partially filled index blocks do count. 12 | 13 | How many bytes are used to lay out the file when using 14 | 15 | a. a FAT file system? 16 | 17 | 676 bytes 18 | 19 | b. a UNIX-style file system? 20 | 21 | Now suppose that you wish to read the 1099'th block of the file. 22 | Assume each of the following counts as one search operation: 23 | moving from one element to the next in a linked list; indexing 24 | into an index block; moving from index block to the next. How 25 | many searches are needed to read block 1099 when using 26 | 27 | c. the same FAT file system? 28 | d. the same UNIX-style file system? 29 | 30 | 2. Suppose you are given a flash memory consisting of 4 KB pages, and 31 | there are 1024 pages. How many bytes of memory would the OS 32 | need to keep track of free space in the worst case (all of flash 33 | memory is free) if 34 | 35 | a. a bitmap was used? 36 | 37 | 1024 bits since all 1024 pages/blocks are free 38 | 39 | b. a linked list was used? Assume 2 bytes/pointer. 40 | 41 | 2048 bytes since each pointer uses 2 bytes and all 1024 pages/blocks are free 42 | 43 | Under what conditions would a linked list be more memory-efficient 44 | than a bitmap? 45 | 46 | The linked list would be more memory efficient when a lot of disk space has been 47 | allocated (not free) since the linked list allocation does not keep track of allocated blocks. 48 | 49 | 3. The read/write head of a disk is at track 97, moving towards track 50 | 199 (the highest-numbered track on the disk), and the disk request 51 | queue contains read/write requests for sectors on tracks 84, 155, 52 | 103, 96, and 197, respectively. Starting from the current head 53 | position, what is the total distance in tracks that the disk arm 54 | moves to satisfy all the pending requests for: 55 | 56 | a. FCFS scheduling 57 | 97 -> 84 -> 155 -> 103 -> 96 -> 197 58 | 13 + 71 + 52 + 7 + 101 = 244 total tracks 59 | 60 | b. SCAN scheduling 61 | 97 -> 103 -> 155 -> 197 -> 199 -> 96 -> 84 62 | 6 + 52 + 42 + 2 + 103 + 12 = 217 total tracks 63 | 64 | c. LOOK scheduling 65 | 97 -> 103 -> 155 -> 197 -> 96 -> 84 66 | 6 + 52 + 42 + 101 + 12 = 213 total tracks 67 | 68 | 4. Describe the SSH protocol in detail, i.e. describe the initial 69 | handshaking phase as well as the subsequent data messaging phase. When a user 70 | supplies their login password, is it encrypted by a public key or a symmetric key, 71 | and why? Explain why or why not SSH is resilient to eavesdropping attacks, 72 | man-in-the-middle attacks, and/or replay attacks. 73 | 74 | 1. Client sends N (the RSA public key) to the server. 75 | 2. Server verifies N using p (the RSA private key) 76 | 3. Client generates a session key K (used as a symmetric key for AES) 77 | 4. Client encrypts K using N (the RSA public key) and sends the encrypted key to the server 78 | 5. Client uses K for AES 79 | 6. Server decrypts the encrypted key and uses K for AES 80 | 7. The SSH session is now encrypted using AES with symmetric key K. All session data sent to/from the server is now encrypted using AES. 81 | 82 | The login password is encrypted using the symmetric key in AES. 83 | SSH is resilient to eavesdropping attacks since the attacker cannot get K without the private key p. 84 | Man-in-the-middle attacks are also useless since the attacker cannot spoof the client since the session is encrypted using symmetric key K. 85 | Replay attacks are also useless since K is randomly generated on each session and will not be the same in future sessions. 86 | -------------------------------------------------------------------------------- /Problem Sets/Set4.md: -------------------------------------------------------------------------------- 1 | Problem 1 2 | --- 3 | Describe at least 3 general approaches in memory management 4 | than can help solve the external fragmentation problem. 5 | 6 | ======= 7 | * Compaction: 8 | * Full Compaction: Move all allocated memory to one side of memory (fix fragmentation) and release the old allocated memory processes. 9 | * Partial Compaction: Move allocated memory and free up memory segments until you have enough memory to honor memory requests. 10 | * With Swapping: Move allocated memory to disk, free up memory after, then reallocate memory with the disk allocated memory contents. 11 | * Paging: Divide the system memory into fixed size pages, selectively allocating pages to frames (a piece/segment of a physical memory), and manage pages in memory with pointers. 12 | * Garbage Collection: Maintain a reference to unused and inaccessible allocated memory and treat it as free memory. 13 | 14 | ======= 15 | Problem 2 16 | --- 17 | A memory manager for a variable-sized region strategy has a 18 | free list of blocks of size 600, 400, 1000, 2200, 1600, and 1050 19 | bytes. What block will be selected to honor a request for: 20 | 21 | ======= 22 | 23 | ``` 24 | a. 1603 bytes using a best-fit policy? 2200 25 | b. 949 bytes using a best-fit policy? 1000 26 | c. 1603 bytes using a worst-fit policy? 2200 27 | d. 349 bytes using a worst-fit policy? 2200 28 | e. 1603 bytes using a first-fit policy? (assume the free list is ordered 29 | as listed above) 2200 30 | f. 1049 using a first-fit policy? 2200 31 | ``` 32 | 33 | ====== 34 | Problem 3 35 | --- 36 | Suppose two processes need to be mapped into main memory 37 | using pages. Process P1 consists of 7 pages, and process P2 38 | consists of 4 pages. Assume main memory consists of 16 frames, a 39 | logical page is the same size as a physical frame, and that 4 40 | entries in a page table fills up a frame of memory. Assume also 41 | that within the process' allocated address spaces, there are two 42 | pages of shared code 'X' and 'Y' common to both address spaces. 43 | Design a memory management system that can store these two 44 | processes and their page tables in RAM. Identify which frames you 45 | have chosen to assign to which process pages and page tables in 46 | main memory/RAM. Also show possible page tables for P1 and P2 47 | (e.g. page table for P1 should have 7 entries). 48 | 49 | ===== 50 | 51 | ![](https://github.com/jon5477/CSCI3753/blob/master/Problem%20Sets/Set4/prob3.jpg) 52 | 53 | ===== 54 | Problem 4 55 | --- 56 | Suppose on-demand paging is employed in addition to TLB 57 | caching. The time for a TLB hit is T = 1 ns, a memory read M = 10 58 | ns, and a disk read D = 10 ms. Let p_TLB = the probability of a 59 | TLB hit, and p = the probability of a page fault given a TLB miss. 60 | What is a general formula for the average memory access time 61 | expressed as a function of T, M, D, p, and p_TLB? Once parameter 62 | values are substituted, and assuming assuming p = .001 and p_TLB = 63 | 90%, what is the calculated average memory access time? 64 | 65 | ===== 66 | 67 | ![](https://github.com/jon5477/CSCI3753/blob/master/Problem%20Sets/Set4/prob4.jpg) 68 | 69 | ===== 70 | Problem 5 71 | --- 72 | The Least Recently Used (LRU) page replacement policy does not 73 | suffer from Belady's Anomaly. Explain intuitively why this is the 74 | case. Construct an example page fault sequence to illustrate your 75 | point. 76 | 77 | ===== 78 | 79 | ![](https://github.com/jon5477/CSCI3753/blob/master/Problem%20Sets/Set4/prob5.jpg) 80 | 81 | ===== 82 | Problem 6 83 | --- 84 | Given a frame allocation of 3, and the following sequence of 85 | page references 3 2 4 3 4 2 2 3 4 5 6 7 7 6 5 4 5 6 7 2 1, and 86 | assuming main memory is initially unloaded, show the page faulting 87 | behavior using the following page replacement policies. How many 88 | page faults are generated by each page replacement algorithm? Which 89 | generates the fewest page faults? 90 | a. FIFO 91 | b. OPT 92 | c. LRU 93 | 94 | ===== 95 | 96 | ![](https://github.com/jon5477/CSCI3753/blob/master/Problem%20Sets/Set4/prob6.jpg) 97 | 98 | ===== 99 | Problem 7 100 | --- 101 | Assume the same sequence of page references as in problem #6, 102 | and assume memory is initially unloaded, but now assume that a dynamic 103 | paging working-set algorithm is applied to the same sequence of 104 | page references, with a window size of 6. Draw the page faulting 105 | behavior. Your solution chart should show the frame allocation at 106 | any given time to the process. 107 | 108 | ===== 109 | 110 | ![](https://github.com/jon5477/CSCI3753/blob/master/Problem%20Sets/Set4/prob7.jpg) 111 | 112 | ===== 113 | -------------------------------------------------------------------------------- /Problem Sets/Set1.md: -------------------------------------------------------------------------------- 1 | Problem Set 1 2 | ============= 3 | **1: Suppose we have a round-robin scheduler in the OS kernel of a preemptively time sliced system, and three programs in its ready queue: P1, P2, and P3. P1 takes 10 seconds to complete, P2 takes 8.5 seconds, and P3 takes 3 seconds. Suppose the time slice is 2 seconds, and the overhead for OS context switching is 0.2 seconds. If P1 starts executing first at time 0, when do each of the programs finish executing? Draw a timeline of execution. What is the percentage overhead due to context switching? Assume that a process that finishes early transfers control back to the OS scheduler.** 4 | 5 | --- 6 | Execution Timeline: 7 | ``` 8 | P1 | P1 | P1 | P1 | P1 9 | | P2 | P2 | P2 | P2 | P2 10 | | P3 | P3 11 | ``` 12 | * Total Execution Time: 23.7 seconds 13 | * P3 Finishes: 12.0 seconds 14 | * P1 Finishes: 23.0 seconds 15 | * P2 Finishes: 23.7 seconds 16 | * Context Switches: 11 times 17 | * Total Time Spent on Context Switches: 2.2 seconds 18 | * Context Switch Overhead (Percent): 10% 19 | 20 | --- 21 | **2: Repeat above for a batch mode multiprogrammed OS. Which system, preemptively multitasked or batch mode multiprogrammed finished execution of all three programs the fastest? Under what conditions might the reverse be true?** 22 | 23 | --- 24 | Execution Timeline: 25 | ``` 26 | P1 27 | | P2 28 | | P3 29 | ``` 30 | * Total Execution Time: 31 | * P1 Finishes: 10 seconds 32 | * P2 Finishes: 18.5 seconds 33 | * P3 Finishes: 21.5 seconds 34 | 35 | Batch Mode Multiprogrammed finished first in this instance. The reverse would be true if a program failed to finish executing (i.e either maliciously or if an error occured [bad fault isolation]) or if the CPU is blocked because of an I/O bound job (i.e reading/writing to disk) in which case other programs would be starved of CPU time and unable to make any progress. 36 | 37 | --- 38 | **3: Explain the differences between the four different kinds of exceptions found in an OS exception table. What is a software interrupt, and how does that differ from a hardware interrupt?** 39 | 40 | --- 41 | Exceptions: 42 | 43 | |Type|Differences| 44 | |----|-----------| 45 | |Trap|Intentional exception used as a "software interrupt" for system calls. Passes control from the application to the kernel.| 46 | |Fault|Exception used for an error that might potentially be recoverable (i.e. page faults, stack overflow, segmentation faults)| 47 | |Interrupt|Exception used as a form of signaling that an I/O task has been completed.| 48 | |Abort|Exception used for serious problems such as hardware failure. There is no recovery here.| 49 | 50 | A software interrupt or trap is a way to process system calls in an application. It causes the current application to halt execution, sets the mode bit to kernel bit, and gives control to the kernel to execute the desired system call. Once the system call completes, the mode bit is set back, and control is given back to the application. 51 | 52 | A hardware interrupt is a way to let the application know that an I/O task has completed (e.g. read/write from/to disk). It allows the current application to not wait on the operating system to return (i.e. completing a system call) for a potentially long running task (such as an I/O operation) and allows the program to be notified of when that task has been completed in the future (asynchronously). Once a hardware interrupt is received, the CPU interrupts normal execution and invokes the operating system's interrupt handler. Once the handler finishes execution, normal execution resumes. 53 | 54 | --- 55 | **4: What role does the jump table play in executing a system call?** 56 | 57 | --- 58 | The trap table contains the memory location (pointer) to the trap handler for the system call in question. The trap handler is then executed and control is given back to the application that called the system call. 59 | 60 | --- 61 | **5: Explain in what way overlapping I/O with CPU processing is advantageous. Explain two ways that I/O can be overlapped with CPU execution and how they are each an improvement over not overlapping I/O with the CPU.** 62 | 63 | --- 64 | Overlapping I/O with CPU processing is very advantageous because it allows the CPU to do something else useful rather than idling or polling the I/O device to check if the I/O task has completed, saving a lot of CPU cycles. The two ways to overlap I/O with CPU execution are direct I/O with interrupts and DMA (Direct Memory Access) with interrupts. The use of direct I/O with interrupts allows the transfer of data to commence without the CPU continually polling to check if the I/O has completed, the CPU receives notification of completion through an interrupt. The use of DMA with interrupts allow the transferring of data from an I/O device to memory without interrupting the CPU multiple times. Instead, the CPU is notified once the data transfer fully completes. This substantially improves the performance of large I/O transfers because the CPU is not constantly being interrupted. 65 | 66 | --- 67 | **6: Describe each step of a write() operation to disk, from the application first calling a write() through the OS processing the write() to the final return from the write() call upon completion of the disk operation. Assume interrupt driven I/O operation. You may draw and label a figure if you'd like. Your answer should include components such as the device controller, interrupt handler, device handler, device driver, and any other OS components you deem appropriate to add.** 68 | 69 | --- 70 | System Call Steps: 71 | 72 | 1. Application calls the system call write() 73 | 2. Trap/"software interrupt" immediately follows 74 | 3. Mode bit is set to kernel bit. 75 | 4. Kernel begins to execute the system write driver 76 | 5. The write driver obtains the status from the device controller 77 | 6. Add to request queue 78 | 7. Give control back to application 79 | 80 | If device is not busy: 81 | 82 | 1. Device handler is executed 83 | 2. Pull data from device controller 84 | 3. Return data to application. 85 | 86 | If device is busy: 87 | 88 | 1. If device is busy, interrupt occurs when it is available 89 | 2. Interrupt handler is executed, find out which device raised the interrupt flag. 90 | 3. Device handler is executed 91 | 4. Pull data from device controller 92 | 5. Return data to application. 93 | -------------------------------------------------------------------------------- /Problem Sets/Set3.md: -------------------------------------------------------------------------------- 1 | Problem 1: To implement deadlock avoidance, the Banker's Algorithm is applied to the following system, where the total number of resources 2 | available for each of four resource types is R0=6, R1=4, R2=4, and 3 | R3=2. Is the system in a safe state? If not, then explain why 4 | not, or if so, find a safe sequence. Show your work. 5 | 6 | Maximum Claims: 7 | 8 | | | R0 | R1 | R2 | R3 | 9 | |----|----|----|----|----| 10 | | P0 | 3 | 2 | 1 | 1 | 11 | | P1 | 1 | 2 | 0 | 2 | 12 | | P2 | 1 | 1 | 2 | 0 | 13 | | P3 | 3 | 2 | 1 | 0 | 14 | | P4 | 2 | 1 | 0 | 1 | 15 | 16 | Current Allocation: 17 | 18 | | | R0 | R1 | R2 | R3 | 19 | |----|----|----|----|----| 20 | | P0 | 2 | 0 | 1 | 0 | 21 | | P1 | 1 | 1 | 0 | 0 | 22 | | P2 | 1 | 1 | 0 | 0 | 23 | | P3 | 1 | 0 | 1 | 0 | 24 | | P4 | 0 | 1 | 0 | 1 | 25 | 26 | === 27 | The system is in a safe state. 28 | 29 | 1. Give resources to P2: 30 | 31 | | R0 | R1 | R2 | R3 | 32 | |----|----|----|----| 33 | | 2 | 2 | 2 | 1 | 34 | 2. Give resources to P3: 35 | 36 | | R0 | R1 | R2 | R3 | 37 | |----|----|----|----| 38 | | 3 | 2 | 3 | 1 | 39 | 3. Give resources to P4: 40 | 41 | | R0 | R1 | R2 | R3 | 42 | |----|----|----|----| 43 | | 3 | 3 | 3 | 2 | 44 | 4. Give resources to P1: 45 | 46 | | R0 | R1 | R2 | R3 | 47 | |----|----|----|----| 48 | | 4 | 4 | 3 | 2 | 49 | 5. Give resources to P0: 50 | 51 | | R0 | R1 | R2 | R3 | 52 | |----|----|----|----| 53 | | 6 | 4 | 4 | 2 | 54 | 55 | === 56 | Problem 2: Suppose we have 5 dining philosophers and 5 shared chopsticks, and that the philosophers are circularly 57 | deadlocked. Assume also that there are two serving spoons, one allocated to philopher 1, and the other available. 58 | Assume that philosopher 4 wants a serving spoon. Show how this situation can be modeled according to the various 59 | data structures, e.g. Allocation and Request matrices, used in the Deadlock detection algorithm. Run the Deadlock 60 | detection algorithm on your model to prove that the dining philosophers are in deadlock. 61 | 62 | === 63 | Let R0 be the chopstick. 64 | Let R1 be the serving spoon. 65 | 66 | Maximum Claims: 67 | 68 | | | R0 | R1 | 69 | |----|----|----| 70 | | P1 | 2 | 1 | 71 | | P2 | 2 | 1 | 72 | | P3 | 2 | 1 | 73 | | P4 | 2 | 1 | 74 | | P5 | 2 | 1 | 75 | 76 | Current Allocation: 77 | 78 | | | R0 | R1 | 79 | |----|----|----| 80 | | P1 | 1 | 1 | 81 | | P2 | 1 | 0 | 82 | | P3 | 1 | 0 | 83 | | P4 | 1 | 0 | 84 | | P5 | 1 | 0 | 85 | 86 | Request: 87 | 88 | | | R0 | R1 | 89 | |----|----|----| 90 | | P1 | 1 | 0 | 91 | | P2 | 1 | 0 | 92 | | P3 | 1 | 0 | 93 | | P4 | 1 | 1 | 94 | | P5 | 1 | 0 | 95 | 96 | All philosophers need 1 more chopstick to eat. However, there are no more available chopsticks (R0) since all have been allocated so there is deadlock. 97 | Serving spoon can be allocated to Philosopher 4 easily since it is available. 98 | 99 | === 100 | Problem 3: Consider the following set of processes, with the length of 101 | the CPU execution time given in seconds: 102 | 103 | | Process | Execution Time | Priority | 104 | |---------|----------------|----------| 105 | | P1 | 10 | 3 | 106 | | P2 | 1 | 1 | 107 | | P3 | 2 | 3 | 108 | | P4 | 1 | 4 | 109 | | P5 | 5 | 2 | 110 | 111 | Draw four Gantt charts that illustrate the timeline of execution of 112 | the processes when scheduled according to FCFS, SJF, nonpreemptive 113 | priority (priority 1 is most important), and round robin (time 114 | slice=1). Which one has the lowest average wait time? Which one 115 | has the lowest average turnaround time? 116 | 117 | === 118 | 119 | ``` 120 | FCFS: 121 | | P1 | P2 | P3 | P4 | P5 | 122 | 0 10 11 13 14 19 123 | ``` 124 | Wait Time: (10 + 11 + 13 + 14) / 5 = 9.6 s 125 | Turnaround Time: (10 + 11 + 13 + 14 + 19) / 5 = 13.4 s 126 | 127 | ``` 128 | SJF: 129 | | P2 | P4 | P3 | P5 | P1 | 130 | 0 1 2 4 9 19 131 | ``` 132 | Wait Time: (1 + 2 + 4 + 9) / 5 = 3.2 s 133 | Turnaround Time: (1 + 2 + 4 + 9 + 19) / 5 = 7.0 s 134 | 135 | ``` 136 | Non-preemptive Priority: 137 | | P2 | P5 | P1 | P3 | P4 | 138 | 0 1 6 16 18 19 139 | ``` 140 | Wait Time: (1 + 6 + 16 + 18) / 5 = 8.2 s 141 | Turnaround Time: (1 + 6 + 16 + 18 + 19) / 5 = 12.0 s 142 | 143 | ``` 144 | Round Robin: 145 | |P1|P2|P3|P4|P5|P1|P3|P5|P1| P5 | P1 | P5 | P1 | P5 | P1 | P1 | P1 | P1 | P1 | 146 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 147 | 148 | ``` 149 | Wait Time: 5.4 s 150 | Turnaround Time: 9.2 s 151 | 152 | SJF has the lowest average wait times and turnaround times. 153 | 154 | === 155 | Problem 4: Suppose the Completely Fair Scheduler (CFS) algorithm is applied to the following scenario. There exist 156 | two processes P1 and P2 that need to be scheduled. P1 has two threads T1 and T2 that are implemented as kernel 157 | threads. P2 has three threads T3, T4, and T5 that are implemented as user space threads. We apply round robin 158 | scheduling to all schedulable tasks, where each task schedulable by the kernel receives a time slice of size T 159 | seconds. 160 | 161 | a. Draw the table of wait times (times owed on an ideal CPU) for one round robin of this scenario, i.e. what are 162 | the wait time balances as each time slice is allocated to a kernel-schedulable task, and what is the final wait 163 | time for each such task? See for example slide 21 of the Chapter 6.3 lecture slides. 164 | 165 | === 166 | 167 | | T1 | T2 | P2 | T1 | 168 | |----|----|----|----| 169 | Time ---> 170 | 171 | |Giving time T to task:| T1 | T2 | T3 | 172 | |----------------------|-----|-----|----| 173 | | T1 |-2T/3|T/3 |T/3 | 174 | | T2 |-1T/3|-1T/3|2T/3| 175 | | P2 | 0 | 0 | 0 | 176 | 177 | === 178 | b. Is this system fair at the level of schedulable tasks? Is this system fair at the level of processes? 179 | Justify your answers. 180 | 181 | === 182 | At the level of schedulable tasks, the system is fair because each task is shared equally. 183 | At the level of processes, the system is not fair since there are shared resources between the processes. 184 | 185 | === 186 | -------------------------------------------------------------------------------- /Problem Sets/Set2.md: -------------------------------------------------------------------------------- 1 | Problem Set 2 2 | ============= 3 | **1. There is a one-lane east-west bridge in Hawaii such that when a car is on the bridge going eastbound, no westbound cars are allowed until the eastbound car has left the bridge. Similarly when a westbound car is on the bridge, no eastbound cars are allowed until the westbound car has left the bridge. To make matters more complicated, if an eastbound car arrives and sees another eastbound car already on the bridge, then that eastbound car will also proceed onto the bridge. This is true even if there is a westbound car already waiting to enter the bridge. Similarly, a westbound car can tailgate behind another westbound car already on the bridge even if an eastbound car was waiting. Deign a synchronization solution using only locks, semaphores and integer variables that achieves the following: allows all cars bound in a certain direction to continue crossing as long as there is at least one car still on the bridge that is bound in that direction, then toggles to allow all cars in the opposite direction to proceed in a similar manner. The solution need not be starvation-free.** 4 | 5 | --- 6 | ``` 7 | lock mutex_lock; 8 | semaphore east_sem, west_sem; 9 | int east_cars = 0, west_cars = 0; 10 | 11 | go_east() { 12 | P(east_sem); 13 | P(mutex_lock); 14 | east_cars++; 15 | if (east_cars == 1) { 16 | P(west_sem); // lock the west side 17 | } 18 | V(mutex_lock); 19 | V(east_sem); 20 | // code to cross the bridge 21 | P(mutex_lock); 22 | east_cars--; 23 | if (!east_cars) { 24 | V(west_sem); // release west side 25 | } 26 | V(mutex_lock); 27 | } 28 | 29 | go_west() { 30 | P(west_sem); 31 | P(mutex_lock); 32 | west_cars++; 33 | if (west_cars == 1) { 34 | P(east_cars); // lock the east side 35 | } 36 | V(mutex_lock); 37 | V(west_sem); 38 | // code to cross the bridge 39 | P(mutex_lock); 40 | west_cars--; 41 | if (!west_cars) { 42 | V(east_sem); // release east side 43 | } 44 | V(mutex_lock); 45 | } 46 | ``` 47 | 48 | --- 49 | **2. Suppose task T1 has code C1 that must execute before task T2's code C2. Design a solution that enforces this ordering using only condition variables, locks, and integer variables. Semaphores and monitors are not allowed.** 50 | 51 | --- 52 | ``` 53 | // this is pseudocode 54 | lock mutex_lock; 55 | condition c; 56 | int t1_complete = 0; 57 | 58 | // Task T1 59 | Acquire(mutex_lock); 60 | // execute code c1 61 | t1_complete = 1; 62 | Release(mutex_lock); 63 | c.signal(); 64 | // End Task T1 65 | 66 | // Task T2 67 | Acquire(mutex_lock); 68 | while (!t1_complete) { 69 | Release(mutex_lock); 70 | c.wait(); 71 | Acquire(mutex_lock); 72 | } 73 | // execute code c2 74 | Release(mutex_lock); 75 | // End Task T2 76 | 77 | ``` 78 | 79 | --- 80 | **3. Explain why the solution to the 3rd Readers/Writers problem is starvation-free.** 81 | 82 | --- 83 | The 3rd solution to the R/W problem is starvation free because of 2 major concepts. When the writing thread wishes to enter into the critical section for writing data, future arrivals of reading threads will have to wait until the writing thread finishes writing while currently reading threads can continue to read. This prevents writer threads from being starved. On the other hand, reading threads are not starved since multiple readers are allowed to access the critical section as long as there are no writer threads. 84 | 85 | --- 86 | **4. a. Is the swap() function below thread-safe or not? Explain your reasoning.** 87 | 88 | ``` 89 | int temp; 90 | 91 | void swap(int *y, int *z) 92 | { 93 | int local; 94 | 95 | local = temp; 96 | temp = *y; 97 | *y = *z; 98 | *z = temp; 99 | temp = local; 100 | 101 | } 102 | ``` 103 | 104 | --- 105 | No, the swap() function is not thread-safe for the following reason. Suppose there were two threads (A and B) that are calling the swap() function. If A enters swap() and halts execution after "*y = *z" (either by interruption or a context switch), the consequence is now that half of a swap has occured and the reference to y is now lost. If a context switch occured in the middle of this swap, the value of temp would be overwritten and the value of y in thread A would be lost (it was previously stored in temp), if A were to resume execution (context switched back) it would essentially use the wrong value of temp. 106 | 107 | --- 108 | **b. Suppose the swap() function above is called by the interrupt service routine (ISR) below. Assume that if swap() is interrupted during normal execution, the ISR below is called and calls swap() again, reentering swap() and executing in the context of the interrupted thread. Is swap() reentrant? Explain your reasoning.** 109 | 110 | ``` 111 | void interrupt_service_routine() 112 | { 113 | int a = 1, b = 2; 114 | swap(&a, &b); 115 | } 116 | ``` 117 | 118 | --- 119 | Yes, swap() is reentrant since there is no use of a semaphore, monitor, or lock whatsoever. Therefore calling this method would pose no risk of deadlock and would execute normally. 120 | 121 | --- 122 | **5. Suppose you are asked to design a server application consisting of two processes P1 and P2, such that (1) P2 is to sleep until woken up by P1, whereupon (2) P2 would take a 10 MB file from P1 and compress it. What forms of IPC would be best suited to implement these types of information sharing? Describe your solution.** 123 | 124 | --- 125 | Memory Sharing IPC would be ideal for this situation since you have a fairly large file (10 MB) that you wish to pass from one process P1 to another process P2. Process P1 could first read the file into main memory, wake process P2 while passing the pointer to memory where the file is stored and wait asynchronously for P2 to complete. Once process P2 wakes, it will synchronize access to that memory and begin to compress the data in that memory location. Once the compression finishes, P2 will release the lock to memory, send an interrupt to P1 to alert that the file has finished compression, and resume sleeping. 126 | 127 | --- 128 | **6. Suppose processes P0 and P1 share variable V1, and processes P1 and P2 share variable V2, while processes P0, P1 and P2 share V3. Operations on V1 are limited to increment() and decrement(). Operations on V2 are limited to square() and squareroot(). Operations on V3 are limited to sin() and cos(). Design a monitor-based solution that synchronizes access to and manipulation of these variables between the three processes so that race conditions are eliminated.** 129 | 130 | --- 131 | ``` 132 | monitor SomeMonitor { 133 | condition c1, c2, c3; 134 | private int v1, v2, v3; 135 | 136 | public function increment() { 137 | c1.wait(); 138 | v1++; 139 | c1.signal(); 140 | } 141 | 142 | public function decrement() { 143 | c1.wait(); 144 | v1--; 145 | c1.signal(); 146 | } 147 | 148 | public function square() { 149 | c2.wait(); 150 | v2 *= v2; 151 | c2.signal(); 152 | } 153 | 154 | public function squareRoot() { 155 | c2.wait(); 156 | v2 = sqrt(v2); 157 | c2.signal(); 158 | } 159 | 160 | public function sin() { 161 | c3.wait(); 162 | v3 = sin(v3); 163 | c3.signal(); 164 | } 165 | 166 | public function cos() { 167 | c3.wait(); 168 | v3 = cos(v3); 169 | c3.signal(); 170 | } 171 | } 172 | ``` 173 | -------------------------------------------------------------------------------- /Labs/Lab4/rw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: rw.c 3 | * Author: Andy Sayler 4 | * Project: CSCI 3753 Programming Assignment 3 5 | * Create Date: 2012/03/19 6 | * Modify Date: 2012/03/20 7 | * Description: A small i/o bound program to copy N bytes from an input 8 | * file to an output file. May read the input file multiple 9 | * times if N is larger than the size of the input file. 10 | */ 11 | 12 | /* Include Flags */ 13 | #define _GNU_SOURCE 14 | 15 | /* System Includes */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | /* Local Defines */ 26 | #define MAXFILENAMELENGTH 80 27 | #define DEFAULT_INPUTFILENAME "rwinput" 28 | #define DEFAULT_OUTPUTFILENAMEBASE "rwoutput" 29 | #define DEFAULT_BLOCKSIZE 1024 30 | #define DEFAULT_TRANSFERSIZE 1024*100 31 | 32 | int main(int argc, char* argv[]){ 33 | 34 | int rv; 35 | int inputFD; 36 | int outputFD; 37 | char inputFilename[MAXFILENAMELENGTH]; 38 | char outputFilename[MAXFILENAMELENGTH]; 39 | char outputFilenameBase[MAXFILENAMELENGTH]; 40 | 41 | ssize_t transfersize = 0; 42 | ssize_t blocksize = 0; 43 | char* transferBuffer = NULL; 44 | ssize_t buffersize; 45 | 46 | ssize_t bytesRead = 0; 47 | ssize_t totalBytesRead = 0; 48 | int totalReads = 0; 49 | ssize_t bytesWritten = 0; 50 | ssize_t totalBytesWritten = 0; 51 | int totalWrites = 0; 52 | int inputFileResets = 0; 53 | 54 | /* Process program arguments to select run-time parameters */ 55 | /* Set supplied transfer size or default if not supplied */ 56 | if(argc < 2){ 57 | transfersize = DEFAULT_TRANSFERSIZE; 58 | } 59 | else{ 60 | transfersize = atol(argv[1]); 61 | if(transfersize < 1){ 62 | fprintf(stderr, "Bad transfersize value\n"); 63 | exit(EXIT_FAILURE); 64 | } 65 | } 66 | /* Set supplied block size or default if not supplied */ 67 | if(argc < 3){ 68 | blocksize = DEFAULT_BLOCKSIZE; 69 | } 70 | else{ 71 | blocksize = atol(argv[2]); 72 | if(blocksize < 1){ 73 | fprintf(stderr, "Bad blocksize value\n"); 74 | exit(EXIT_FAILURE); 75 | } 76 | } 77 | /* Set supplied input filename or default if not supplied */ 78 | if(argc < 4){ 79 | if(strnlen(DEFAULT_INPUTFILENAME, MAXFILENAMELENGTH) >= MAXFILENAMELENGTH){ 80 | fprintf(stderr, "Default input filename too long\n"); 81 | exit(EXIT_FAILURE); 82 | } 83 | strncpy(inputFilename, DEFAULT_INPUTFILENAME, MAXFILENAMELENGTH); 84 | } 85 | else{ 86 | if(strnlen(argv[3], MAXFILENAMELENGTH) >= MAXFILENAMELENGTH){ 87 | fprintf(stderr, "Input filename too long\n"); 88 | exit(EXIT_FAILURE); 89 | } 90 | strncpy(inputFilename, argv[3], MAXFILENAMELENGTH); 91 | } 92 | /* Set supplied output filename base or default if not supplied */ 93 | if(argc < 5){ 94 | if(strnlen(DEFAULT_OUTPUTFILENAMEBASE, MAXFILENAMELENGTH) >= MAXFILENAMELENGTH){ 95 | fprintf(stderr, "Default output filename base too long\n"); 96 | exit(EXIT_FAILURE); 97 | } 98 | strncpy(outputFilenameBase, DEFAULT_OUTPUTFILENAMEBASE, MAXFILENAMELENGTH); 99 | } 100 | else{ 101 | if(strnlen(argv[4], MAXFILENAMELENGTH) >= MAXFILENAMELENGTH){ 102 | fprintf(stderr, "Output filename base is too long\n"); 103 | exit(EXIT_FAILURE); 104 | } 105 | strncpy(outputFilenameBase, argv[4], MAXFILENAMELENGTH); 106 | } 107 | 108 | /* Confirm blocksize is multiple of and less than transfersize*/ 109 | if(blocksize > transfersize){ 110 | fprintf(stderr, "blocksize can not exceed transfersize\n"); 111 | exit(EXIT_FAILURE); 112 | } 113 | if(transfersize % blocksize){ 114 | fprintf(stderr, "blocksize must be multiple of transfersize\n"); 115 | exit(EXIT_FAILURE); 116 | } 117 | 118 | /* Allocate buffer space */ 119 | buffersize = blocksize; 120 | if(!(transferBuffer = malloc(buffersize*sizeof(*transferBuffer)))){ 121 | perror("Failed to allocate transfer buffer"); 122 | exit(EXIT_FAILURE); 123 | } 124 | 125 | /* Open Input File Descriptor in Read Only mode */ 126 | if((inputFD = open(inputFilename, O_RDONLY | O_SYNC)) < 0){ 127 | perror("Failed to open input file"); 128 | exit(EXIT_FAILURE); 129 | } 130 | 131 | /* Open Output File Descriptor in Write Only mode with standard permissions*/ 132 | rv = snprintf(outputFilename, MAXFILENAMELENGTH, "%s-%d", 133 | outputFilenameBase, getpid()); 134 | if(rv > MAXFILENAMELENGTH){ 135 | fprintf(stderr, "Output filenmae length exceeds limit of %d characters.\n", 136 | MAXFILENAMELENGTH); 137 | exit(EXIT_FAILURE); 138 | } 139 | else if(rv < 0){ 140 | perror("Failed to generate output filename"); 141 | exit(EXIT_FAILURE); 142 | } 143 | if((outputFD = 144 | open(outputFilename, 145 | O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 146 | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)) < 0){ 147 | perror("Failed to open output file"); 148 | exit(EXIT_FAILURE); 149 | } 150 | 151 | /* Print Status */ 152 | fprintf(stdout, "Reading from %s and writing to %s\n", 153 | inputFilename, outputFilename); 154 | 155 | /* Read from input file and write to output file*/ 156 | do{ 157 | /* Read transfersize bytes from input file*/ 158 | bytesRead = read(inputFD, transferBuffer, buffersize); 159 | if(bytesRead < 0){ 160 | perror("Error reading input file"); 161 | exit(EXIT_FAILURE); 162 | } 163 | else{ 164 | totalBytesRead += bytesRead; 165 | totalReads++; 166 | } 167 | 168 | /* If all bytes were read, write to output file*/ 169 | if(bytesRead == blocksize){ 170 | bytesWritten = write(outputFD, transferBuffer, bytesRead); 171 | if(bytesWritten < 0){ 172 | perror("Error writing output file"); 173 | exit(EXIT_FAILURE); 174 | } 175 | else{ 176 | totalBytesWritten += bytesWritten; 177 | totalWrites++; 178 | } 179 | } 180 | /* Otherwise assume we have reached the end of the input file and reset */ 181 | else{ 182 | if(lseek(inputFD, 0, SEEK_SET)){ 183 | perror("Error resetting to beginning of file"); 184 | exit(EXIT_FAILURE); 185 | } 186 | inputFileResets++; 187 | } 188 | 189 | }while(totalBytesWritten < transfersize); 190 | 191 | /* Output some possibly helpfull info to make it seem like we were doing stuff */ 192 | fprintf(stdout, "Read: %zd bytes in %d reads\n", 193 | totalBytesRead, totalReads); 194 | fprintf(stdout, "Written: %zd bytes in %d writes\n", 195 | totalBytesWritten, totalWrites); 196 | fprintf(stdout, "Read input file in %d pass%s\n", 197 | (inputFileResets + 1), (inputFileResets ? "es" : "")); 198 | fprintf(stdout, "Processed %zd bytes in blocks of %zd bytes\n", 199 | transfersize, blocksize); 200 | 201 | /* Free Buffer */ 202 | free(transferBuffer); 203 | 204 | /* Close Output File Descriptor */ 205 | if(close(outputFD)){ 206 | perror("Failed to close output file"); 207 | exit(EXIT_FAILURE); 208 | } 209 | 210 | /* Close Input File Descriptor */ 211 | if(close(inputFD)){ 212 | perror("Failed to close input file"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | return EXIT_SUCCESS; 217 | } 218 | -------------------------------------------------------------------------------- /Labs/Lab5/xattr-util.c: -------------------------------------------------------------------------------- 1 | /* aes-crypt.c 2 | * Extended attribute manipulation demo program 3 | * 4 | * See aes-crypt.h and aes-crypt.c for more details 5 | * 6 | * By Andy Sayler (www.andysayler.com) 7 | * Created 04/17/12 8 | * Modified 04/18/12 9 | * 10 | * Note: The most common issues here are neglecting the necessary namespace 11 | * prefixes on attribute names, or using a file system that does not 12 | * support extended attributes. For namespace info, see 13 | * http://www.freedesktop.org/wiki/CommonExtendedAttributes. 14 | * For info on enabling xattr on EXT file systems, see 15 | * http://wiki.kaspersandberg.com/doku.php?id=howtos:xattr#getting_ea_s_enabled 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define CMDLS "-l" 29 | #define CMDSET "-s" 30 | #define CMDGET "-g" 31 | #define CMDREM "-r" 32 | #define USAGE_GENERAL " " 33 | #define USAGE_LIST CMDLS " " 34 | #define USAGE_SET CMDSET " " 35 | #define USAGE_GET CMDGET " " 36 | #define USAGE_REM CMDREM " " 37 | 38 | #ifdef linux 39 | /* Linux is missing ENOATTR error, using ENODATA instead */ 40 | #define ENOATTR ENODATA 41 | #endif 42 | 43 | /* Add namespace defintion for older kernels. Normally included in linux/xattr.h */ 44 | #ifndef XATTR_USER_PREFIX 45 | #define XATTR_USER_PREFIX "user." 46 | #define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) 47 | #endif 48 | 49 | static void printUsageGeneral(char* pgmName){ 50 | fprintf(stderr, "Usage: %s %s\n", 51 | pgmName, USAGE_GENERAL); 52 | } 53 | 54 | static void printUsageList(char* pgmName){ 55 | fprintf(stderr, "Usage: %s %s\n", 56 | pgmName, USAGE_LIST); 57 | } 58 | 59 | static void printUsageSet(char* pgmName){ 60 | fprintf(stderr, "Usage: %s %s\n", 61 | pgmName, USAGE_SET); 62 | } 63 | 64 | static void printUsageGet(char* pgmName){ 65 | fprintf(stderr, "Usage: %s %s\n", 66 | pgmName, USAGE_GET); 67 | } 68 | 69 | static void printUsageRem(char* pgmName){ 70 | fprintf(stderr, "Usage: %s %s\n", 71 | pgmName, USAGE_REM); 72 | } 73 | 74 | int main(int argc, char* argv[]){ 75 | 76 | /* Local vars */ 77 | char* lst = NULL; 78 | char* chr = NULL; 79 | char* start = NULL; 80 | char* tmpstr = NULL; 81 | char* tmpval = NULL; 82 | ssize_t cnt = 0; 83 | ssize_t lstsize = 0; 84 | ssize_t valsize = 0; 85 | 86 | /* Check base input */ 87 | if(argc < 2){ 88 | printUsageGeneral(argv[0]); 89 | exit(EXIT_FAILURE); 90 | } 91 | 92 | /* Parse Command */ 93 | if(!strcmp(argv[1], CMDLS)){ 94 | /* List Case */ 95 | /* Check proper input */ 96 | if(argc != 3){ 97 | printUsageList(argv[0]); 98 | exit(EXIT_FAILURE); 99 | } 100 | /* Call xattr list to get size */ 101 | lstsize = listxattr(argv[2], NULL, 0); 102 | if(lstsize < 0){ 103 | perror("listxattr error"); 104 | fprintf(stderr, "path = %s\n", argv[2]); 105 | exit(EXIT_FAILURE); 106 | } 107 | /* Malloc space for list items */ 108 | lst = malloc(sizeof(*lst)*lstsize); 109 | if(!lst){ 110 | perror("malloc of 'lst' error"); 111 | exit(EXIT_FAILURE); 112 | } 113 | /* Call xattr list to get data */ 114 | lstsize = listxattr(argv[2], lst, lstsize); 115 | if(lstsize < 0 || !lst){ 116 | perror("listxattr error"); 117 | fprintf(stderr, "path = %s\n", argv[2]); 118 | exit(EXIT_FAILURE); 119 | } 120 | /* Tokenize null seperated array on \0 */ 121 | chr = start = lst; 122 | cnt = 0; 123 | while(cnt < lstsize){ 124 | /* Print attribute names, one per line */ 125 | fprintf(stdout, "%s\n", start); 126 | while(*chr != '\0'){ 127 | chr++; 128 | cnt++; 129 | } 130 | start = ++chr; 131 | cnt++; 132 | } 133 | } 134 | else if(!strcmp(argv[1], CMDSET)){ 135 | /* Set Case */ 136 | /* Check proper input */ 137 | if(argc != 5){ 138 | printUsageSet(argv[0]); 139 | exit(EXIT_FAILURE); 140 | } 141 | /* Append necessary 'user.' namespace prefix to beginning of name string */ 142 | tmpstr = malloc(strlen(argv[2]) + XATTR_USER_PREFIX_LEN + 1); 143 | if(!tmpstr){ 144 | perror("malloc of 'tmpstr' error"); 145 | exit(EXIT_FAILURE); 146 | } 147 | strcpy(tmpstr, XATTR_USER_PREFIX); 148 | strcat(tmpstr, argv[2]); 149 | /* Set attribute */ 150 | if(setxattr(argv[4], tmpstr, argv[3], strlen(argv[3]), 0)){ 151 | perror("setxattr error"); 152 | fprintf(stderr, "path = %s\n", argv[4]); 153 | fprintf(stderr, "name = %s\n", tmpstr); 154 | fprintf(stderr, "value = %s\n", argv[3]); 155 | fprintf(stderr, "size = %zd\n", strlen(argv[3])); 156 | exit(EXIT_FAILURE); 157 | } 158 | /* Cleanup */ 159 | free(tmpstr); 160 | } 161 | else if(!strcmp(argv[1], CMDGET)){ 162 | /* Get Case */ 163 | /* Check proper input */ 164 | if(argc != 4){ 165 | printUsageGet(argv[0]); 166 | exit(EXIT_FAILURE); 167 | } 168 | /* Append necessary 'user.' namespace prefix to beginning of name string */ 169 | tmpstr = malloc(strlen(argv[2]) + XATTR_USER_PREFIX_LEN + 1); 170 | if(!tmpstr){ 171 | perror("malloc of 'tmpstr' error"); 172 | exit(EXIT_FAILURE); 173 | } 174 | strcpy(tmpstr, XATTR_USER_PREFIX); 175 | strcat(tmpstr, argv[2]); 176 | /* Get attribute value size */ 177 | valsize = getxattr(argv[3], tmpstr, NULL, 0); 178 | if(valsize < 0){ 179 | if(errno == ENOATTR){ 180 | fprintf(stdout, "No %s attribute set on %s\n", tmpstr, argv[3]); 181 | free(tmpstr); 182 | return EXIT_SUCCESS; 183 | } 184 | else{ 185 | perror("getxattr error"); 186 | fprintf(stderr, "path = %s\n", argv[3]); 187 | fprintf(stderr, "name = %s\n", tmpstr); 188 | fprintf(stderr, "value = %s\n", "NULL"); 189 | fprintf(stderr, "size = %zd\n", valsize); 190 | exit(EXIT_FAILURE); 191 | } 192 | } 193 | /* Malloc Value Space */ 194 | tmpval = malloc(sizeof(*tmpval)*(valsize+1)); 195 | if(!tmpval){ 196 | perror("malloc of 'tmpval' error"); 197 | exit(EXIT_FAILURE); 198 | } 199 | /* Get attribute value */ 200 | valsize = getxattr(argv[3], tmpstr, tmpval, valsize); 201 | if(valsize < 0){ 202 | if(errno == ENOATTR){ 203 | fprintf(stdout, "No %s attribute set on %s\n", tmpstr, argv[3]); 204 | free(tmpval); 205 | free(tmpstr); 206 | return EXIT_SUCCESS; 207 | } 208 | else{ 209 | perror("getxattr error"); 210 | fprintf(stderr, "path = %s\n", argv[3]); 211 | fprintf(stderr, "name = %s\n", tmpstr); 212 | fprintf(stderr, "value = %s\n", tmpval); 213 | fprintf(stderr, "size = %zd\n", valsize); 214 | exit(EXIT_FAILURE); 215 | } 216 | } 217 | 218 | /* Print Value */ 219 | tmpval[valsize] = '\0'; 220 | fprintf(stdout, "%s = %s\n", tmpstr, tmpval); 221 | 222 | /* Clean Up */ 223 | free(tmpval); 224 | free(tmpstr); 225 | } 226 | else if(!strcmp(argv[1], CMDREM)){ 227 | /* Remove Case */ 228 | /* Check proper input */ 229 | if(argc != 4){ 230 | printUsageRem(argv[0]); 231 | exit(EXIT_FAILURE); 232 | } 233 | /* Append necessary 'user.' namespace prefix to beginning of name string */ 234 | tmpstr = malloc(strlen(argv[2]) + XATTR_USER_PREFIX_LEN + 1); 235 | if(!tmpstr){ 236 | perror("malloc of 'tmpstr' error"); 237 | exit(EXIT_FAILURE); 238 | } 239 | strcpy(tmpstr, XATTR_USER_PREFIX); 240 | strcat(tmpstr, argv[2]); 241 | /* Remove Attr */ 242 | if(removexattr(argv[3], tmpstr)){ 243 | if(errno == ENOATTR){ 244 | fprintf(stdout, "No %s attribute set on %s\n", tmpstr, argv[3]); 245 | free(tmpstr); 246 | return EXIT_SUCCESS; 247 | } 248 | else{ 249 | perror("removexattr error"); 250 | fprintf(stderr, "path = %s\n", argv[3]); 251 | fprintf(stderr, "name = %s\n", tmpstr); 252 | exit(EXIT_FAILURE); 253 | } 254 | } 255 | /* Cleanup */ 256 | free(tmpstr); 257 | } 258 | else{ 259 | /* Bad Case */ 260 | fprintf(stderr, "Unrecognized option\n"); 261 | exit(EXIT_FAILURE); 262 | } 263 | 264 | return EXIT_SUCCESS; 265 | } 266 | -------------------------------------------------------------------------------- /Labs/Lab5/fusexmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | Minor modifications and note by Andy Sayler (2012) 6 | 7 | Source: fuse-2.8.7.tar.gz examples directory 8 | http://sourceforge.net/projects/fuse/files/fuse-2.X/ 9 | 10 | This program can be distributed under the terms of the GNU GPL. 11 | See the file COPYING. 12 | 13 | gcc -Wall `pkg-config fuse --cflags` fusexmp.c -o fusexmp `pkg-config fuse --libs` 14 | 15 | Note: This implementation is largely stateless and does not maintain 16 | open file handels between open and release calls (fi->fh). 17 | Instead, files are opened and closed as necessary inside read(), write(), 18 | etc calls. As such, the functions that rely on maintaining file handles are 19 | not implmented (fgetattr(), etc). Those seeking a more efficient and 20 | more complete implementation may wish to add fi->fh support to minimize 21 | open() and close() calls and support fh dependent functions. 22 | 23 | */ 24 | 25 | #define FUSE_USE_VERSION 28 26 | #define HAVE_SETXATTR 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include 30 | #endif 31 | 32 | #ifdef linux 33 | /* For pread()/pwrite() */ 34 | #define _XOPEN_SOURCE 500 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #ifdef HAVE_SETXATTR 46 | #include 47 | #endif 48 | 49 | static int xmp_getattr(const char *path, struct stat *stbuf) 50 | { 51 | int res; 52 | 53 | res = lstat(path, stbuf); 54 | if (res == -1) 55 | return -errno; 56 | 57 | return 0; 58 | } 59 | 60 | static int xmp_access(const char *path, int mask) 61 | { 62 | int res; 63 | 64 | res = access(path, mask); 65 | if (res == -1) 66 | return -errno; 67 | 68 | return 0; 69 | } 70 | 71 | static int xmp_readlink(const char *path, char *buf, size_t size) 72 | { 73 | int res; 74 | 75 | res = readlink(path, buf, size - 1); 76 | if (res == -1) 77 | return -errno; 78 | 79 | buf[res] = '\0'; 80 | return 0; 81 | } 82 | 83 | 84 | static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 85 | off_t offset, struct fuse_file_info *fi) 86 | { 87 | DIR *dp; 88 | struct dirent *de; 89 | 90 | (void) offset; 91 | (void) fi; 92 | 93 | dp = opendir(path); 94 | if (dp == NULL) 95 | return -errno; 96 | 97 | while ((de = readdir(dp)) != NULL) { 98 | struct stat st; 99 | memset(&st, 0, sizeof(st)); 100 | st.st_ino = de->d_ino; 101 | st.st_mode = de->d_type << 12; 102 | if (filler(buf, de->d_name, &st, 0)) 103 | break; 104 | } 105 | 106 | closedir(dp); 107 | return 0; 108 | } 109 | 110 | static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) 111 | { 112 | int res; 113 | 114 | /* On Linux this could just be 'mknod(path, mode, rdev)' but this 115 | is more portable */ 116 | if (S_ISREG(mode)) { 117 | res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); 118 | if (res >= 0) 119 | res = close(res); 120 | } else if (S_ISFIFO(mode)) 121 | res = mkfifo(path, mode); 122 | else 123 | res = mknod(path, mode, rdev); 124 | if (res == -1) 125 | return -errno; 126 | 127 | return 0; 128 | } 129 | 130 | static int xmp_mkdir(const char *path, mode_t mode) 131 | { 132 | int res; 133 | 134 | res = mkdir(path, mode); 135 | if (res == -1) 136 | return -errno; 137 | 138 | return 0; 139 | } 140 | 141 | static int xmp_unlink(const char *path) 142 | { 143 | int res; 144 | 145 | res = unlink(path); 146 | if (res == -1) 147 | return -errno; 148 | 149 | return 0; 150 | } 151 | 152 | static int xmp_rmdir(const char *path) 153 | { 154 | int res; 155 | 156 | res = rmdir(path); 157 | if (res == -1) 158 | return -errno; 159 | 160 | return 0; 161 | } 162 | 163 | static int xmp_symlink(const char *from, const char *to) 164 | { 165 | int res; 166 | 167 | res = symlink(from, to); 168 | if (res == -1) 169 | return -errno; 170 | 171 | return 0; 172 | } 173 | 174 | static int xmp_rename(const char *from, const char *to) 175 | { 176 | int res; 177 | 178 | res = rename(from, to); 179 | if (res == -1) 180 | return -errno; 181 | 182 | return 0; 183 | } 184 | 185 | static int xmp_link(const char *from, const char *to) 186 | { 187 | int res; 188 | 189 | res = link(from, to); 190 | if (res == -1) 191 | return -errno; 192 | 193 | return 0; 194 | } 195 | 196 | static int xmp_chmod(const char *path, mode_t mode) 197 | { 198 | int res; 199 | 200 | res = chmod(path, mode); 201 | if (res == -1) 202 | return -errno; 203 | 204 | return 0; 205 | } 206 | 207 | static int xmp_chown(const char *path, uid_t uid, gid_t gid) 208 | { 209 | int res; 210 | 211 | res = lchown(path, uid, gid); 212 | if (res == -1) 213 | return -errno; 214 | 215 | return 0; 216 | } 217 | 218 | static int xmp_truncate(const char *path, off_t size) 219 | { 220 | int res; 221 | 222 | res = truncate(path, size); 223 | if (res == -1) 224 | return -errno; 225 | 226 | return 0; 227 | } 228 | 229 | static int xmp_utimens(const char *path, const struct timespec ts[2]) 230 | { 231 | int res; 232 | struct timeval tv[2]; 233 | 234 | tv[0].tv_sec = ts[0].tv_sec; 235 | tv[0].tv_usec = ts[0].tv_nsec / 1000; 236 | tv[1].tv_sec = ts[1].tv_sec; 237 | tv[1].tv_usec = ts[1].tv_nsec / 1000; 238 | 239 | res = utimes(path, tv); 240 | if (res == -1) 241 | return -errno; 242 | 243 | return 0; 244 | } 245 | 246 | static int xmp_open(const char *path, struct fuse_file_info *fi) 247 | { 248 | int res; 249 | 250 | res = open(path, fi->flags); 251 | if (res == -1) 252 | return -errno; 253 | 254 | close(res); 255 | return 0; 256 | } 257 | 258 | static int xmp_read(const char *path, char *buf, size_t size, off_t offset, 259 | struct fuse_file_info *fi) 260 | { 261 | int fd; 262 | int res; 263 | 264 | (void) fi; 265 | fd = open(path, O_RDONLY); 266 | if (fd == -1) 267 | return -errno; 268 | 269 | res = pread(fd, buf, size, offset); 270 | if (res == -1) 271 | res = -errno; 272 | 273 | close(fd); 274 | return res; 275 | } 276 | 277 | static int xmp_write(const char *path, const char *buf, size_t size, 278 | off_t offset, struct fuse_file_info *fi) 279 | { 280 | int fd; 281 | int res; 282 | 283 | (void) fi; 284 | fd = open(path, O_WRONLY); 285 | if (fd == -1) 286 | return -errno; 287 | 288 | res = pwrite(fd, buf, size, offset); 289 | if (res == -1) 290 | res = -errno; 291 | 292 | close(fd); 293 | return res; 294 | } 295 | 296 | static int xmp_statfs(const char *path, struct statvfs *stbuf) 297 | { 298 | int res; 299 | 300 | res = statvfs(path, stbuf); 301 | if (res == -1) 302 | return -errno; 303 | 304 | return 0; 305 | } 306 | 307 | static int xmp_create(const char* path, mode_t mode, struct fuse_file_info* fi) { 308 | 309 | (void) fi; 310 | 311 | int res; 312 | res = creat(path, mode); 313 | if(res == -1) 314 | return -errno; 315 | 316 | close(res); 317 | 318 | return 0; 319 | } 320 | 321 | 322 | static int xmp_release(const char *path, struct fuse_file_info *fi) 323 | { 324 | /* Just a stub. This method is optional and can safely be left 325 | unimplemented */ 326 | 327 | (void) path; 328 | (void) fi; 329 | return 0; 330 | } 331 | 332 | static int xmp_fsync(const char *path, int isdatasync, 333 | struct fuse_file_info *fi) 334 | { 335 | /* Just a stub. This method is optional and can safely be left 336 | unimplemented */ 337 | 338 | (void) path; 339 | (void) isdatasync; 340 | (void) fi; 341 | return 0; 342 | } 343 | 344 | #ifdef HAVE_SETXATTR 345 | static int xmp_setxattr(const char *path, const char *name, const char *value, 346 | size_t size, int flags) 347 | { 348 | int res = lsetxattr(path, name, value, size, flags); 349 | if (res == -1) 350 | return -errno; 351 | return 0; 352 | } 353 | 354 | static int xmp_getxattr(const char *path, const char *name, char *value, 355 | size_t size) 356 | { 357 | int res = lgetxattr(path, name, value, size); 358 | if (res == -1) 359 | return -errno; 360 | return res; 361 | } 362 | 363 | static int xmp_listxattr(const char *path, char *list, size_t size) 364 | { 365 | int res = llistxattr(path, list, size); 366 | if (res == -1) 367 | return -errno; 368 | return res; 369 | } 370 | 371 | static int xmp_removexattr(const char *path, const char *name) 372 | { 373 | int res = lremovexattr(path, name); 374 | if (res == -1) 375 | return -errno; 376 | return 0; 377 | } 378 | #endif /* HAVE_SETXATTR */ 379 | 380 | static struct fuse_operations xmp_oper = { 381 | .getattr = xmp_getattr, 382 | .access = xmp_access, 383 | .readlink = xmp_readlink, 384 | .readdir = xmp_readdir, 385 | .mknod = xmp_mknod, 386 | .mkdir = xmp_mkdir, 387 | .symlink = xmp_symlink, 388 | .unlink = xmp_unlink, 389 | .rmdir = xmp_rmdir, 390 | .rename = xmp_rename, 391 | .link = xmp_link, 392 | .chmod = xmp_chmod, 393 | .chown = xmp_chown, 394 | .truncate = xmp_truncate, 395 | .utimens = xmp_utimens, 396 | .open = xmp_open, 397 | .read = xmp_read, 398 | .write = xmp_write, 399 | .statfs = xmp_statfs, 400 | .create = xmp_create, 401 | .release = xmp_release, 402 | .fsync = xmp_fsync, 403 | #ifdef HAVE_SETXATTR 404 | .setxattr = xmp_setxattr, 405 | .getxattr = xmp_getxattr, 406 | .listxattr = xmp_listxattr, 407 | .removexattr = xmp_removexattr, 408 | #endif 409 | }; 410 | 411 | int main(int argc, char *argv[]) 412 | { 413 | umask(0); 414 | return fuse_main(argc, argv, &xmp_oper, NULL); 415 | } 416 | -------------------------------------------------------------------------------- /Labs/Lab5/pa5-encfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | Minor modifications and note by Andy Sayler (2012) 6 | 7 | Source: fuse-2.8.7.tar.gz examples directory 8 | http://sourceforge.net/projects/fuse/files/fuse-2.X/ 9 | 10 | This program can be distributed under the terms of the GNU GPL. 11 | See the file COPYING. 12 | 13 | gcc -Wall `pkg-config fuse --cflags` fusexmp.c -o fusexmp `pkg-config fuse --libs` 14 | 15 | Note: This implementation is largely stateless and does not maintain 16 | open file handels between open and release calls (fi->fh). 17 | Instead, files are opened and closed as necessary inside read(), write(), 18 | etc calls. As such, the functions that rely on maintaining file handles are 19 | not implmented (fgetattr(), etc). Those seeking a more efficient and 20 | more complete implementation may wish to add fi->fh support to minimize 21 | open() and close() calls and support fh dependent functions. 22 | 23 | */ 24 | 25 | #define FUSE_USE_VERSION 28 26 | #define HAVE_SETXATTR 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include 30 | #endif 31 | 32 | #ifdef linux 33 | /* For pread()/pwrite() */ 34 | #define _XOPEN_SOURCE 500 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include "aes-crypt.h" 47 | #ifdef HAVE_SETXATTR 48 | #include 49 | #endif 50 | 51 | #define ENC_PARAMS ((EncryptionParams*) fuse_get_context()->private_data) 52 | 53 | typedef struct { 54 | char* key; 55 | char* dir; 56 | } EncryptionParams; 57 | 58 | char* get_path(const char *path) { 59 | int len = strlen(path) + strlen(ENC_PARAMS->dir) + 1; 60 | char* ret = malloc(sizeof(char) * len); 61 | strcpy(ret, ENC_PARAMS->dir); 62 | strcat(ret, path); 63 | return ret; 64 | } 65 | 66 | static int xmp_getattr(const char *fpath, struct stat *stbuf) { 67 | char *path = get_path(fpath); 68 | int res; 69 | res = lstat(path, stbuf); 70 | if (res == -1) { 71 | return -errno; 72 | } 73 | return 0; 74 | } 75 | 76 | static int xmp_access(const char *fpath, int mask) { 77 | char *path = get_path(fpath); 78 | int res; 79 | res = access(path, mask); 80 | if (res == -1) { 81 | return -errno; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | static int xmp_readlink(const char *fpath, char *buf, size_t size) { 88 | char *path = get_path(fpath); 89 | int res; 90 | res = readlink(path, buf, size - 1); 91 | if (res == -1) { 92 | return -errno; 93 | } 94 | buf[res] = '\0'; 95 | return 0; 96 | } 97 | 98 | static int xmp_readdir(const char *fpath, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { 99 | char *path = get_path(fpath); 100 | DIR *dp; 101 | struct dirent *de; 102 | 103 | (void) offset; 104 | (void) fi; 105 | 106 | dp = opendir(path); 107 | if (dp == NULL) 108 | return -errno; 109 | 110 | while ((de = readdir(dp)) != NULL) { 111 | struct stat st; 112 | memset(&st, 0, sizeof(st)); 113 | st.st_ino = de->d_ino; 114 | st.st_mode = de->d_type << 12; 115 | if (filler(buf, de->d_name, &st, 0)) 116 | break; 117 | } 118 | 119 | closedir(dp); 120 | return 0; 121 | } 122 | 123 | static int xmp_mknod(const char *fpath, mode_t mode, dev_t rdev) { 124 | char *path = get_path(fpath); 125 | int res; 126 | 127 | /* On Linux this could just be 'mknod(path, mode, rdev)' but this 128 | is more portable */ 129 | if (S_ISREG(mode)) { 130 | res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); 131 | if (res >= 0) 132 | res = close(res); 133 | } else if (S_ISFIFO(mode)) 134 | res = mkfifo(path, mode); 135 | else 136 | res = mknod(path, mode, rdev); 137 | if (res == -1) 138 | return -errno; 139 | 140 | return 0; 141 | } 142 | 143 | static int xmp_mkdir(const char *fpath, mode_t mode) { 144 | char *path = get_path(fpath); 145 | int res; 146 | 147 | res = mkdir(path, mode); 148 | if (res == -1) 149 | return -errno; 150 | 151 | return 0; 152 | } 153 | 154 | static int xmp_unlink(const char *fpath) { 155 | char *path = get_path(fpath); 156 | int res; 157 | 158 | res = unlink(path); 159 | if (res == -1) 160 | return -errno; 161 | 162 | return 0; 163 | } 164 | 165 | static int xmp_rmdir(const char *fpath) { 166 | char *path = get_path(fpath); 167 | int res; 168 | 169 | res = rmdir(path); 170 | if (res == -1) 171 | return -errno; 172 | 173 | return 0; 174 | } 175 | 176 | static int xmp_symlink(const char *from, const char *to) { 177 | int res; 178 | 179 | res = symlink(from, to); 180 | if (res == -1) 181 | return -errno; 182 | 183 | return 0; 184 | } 185 | 186 | static int xmp_rename(const char *from, const char *to) { 187 | int res; 188 | 189 | res = rename(from, to); 190 | if (res == -1) 191 | return -errno; 192 | 193 | return 0; 194 | } 195 | 196 | static int xmp_link(const char *from, const char *to) { 197 | int res; 198 | 199 | res = link(from, to); 200 | if (res == -1) 201 | return -errno; 202 | 203 | return 0; 204 | } 205 | 206 | static int xmp_chmod(const char *fpath, mode_t mode) { 207 | char *path = get_path(fpath); 208 | int res; 209 | 210 | res = chmod(path, mode); 211 | if (res == -1) 212 | return -errno; 213 | 214 | return 0; 215 | } 216 | 217 | static int xmp_chown(const char *fpath, uid_t uid, gid_t gid) { 218 | char *path = get_path(fpath); 219 | int res; 220 | 221 | res = lchown(path, uid, gid); 222 | if (res == -1) 223 | return -errno; 224 | 225 | return 0; 226 | } 227 | 228 | static int xmp_truncate(const char *fpath, off_t size) { 229 | char *path = get_path(fpath); 230 | int res; 231 | 232 | res = truncate(path, size); 233 | if (res == -1) 234 | return -errno; 235 | 236 | return 0; 237 | } 238 | 239 | static int xmp_utimens(const char *fpath, const struct timespec ts[2]) { 240 | char *path = get_path(fpath); 241 | int res; 242 | struct timeval tv[2]; 243 | 244 | tv[0].tv_sec = ts[0].tv_sec; 245 | tv[0].tv_usec = ts[0].tv_nsec / 1000; 246 | tv[1].tv_sec = ts[1].tv_sec; 247 | tv[1].tv_usec = ts[1].tv_nsec / 1000; 248 | 249 | res = utimes(path, tv); 250 | if (res == -1) 251 | return -errno; 252 | 253 | return 0; 254 | } 255 | 256 | static int xmp_open(const char *fpath, struct fuse_file_info *fi) { 257 | char *path = get_path(fpath); 258 | int res; 259 | 260 | res = open(path, fi->flags); 261 | if (res == -1) 262 | return -errno; 263 | 264 | close(res); 265 | return 0; 266 | } 267 | 268 | int is_encrypted(const char *path) { 269 | int ret; 270 | char xattr_val[5]; 271 | getxattr(path, "user.enc", xattr_val, sizeof(char)*5); 272 | ret = (strcmp(xattr_val, "true") == 0); 273 | return ret; 274 | } 275 | 276 | /*static int file_size(FILE *file) { 277 | struct stat st; 278 | if (fstat(fileno(file), &st) == 0) { 279 | return st.st_size; 280 | } 281 | return -1; 282 | }*/ 283 | 284 | static int xmp_read(const char *fpath, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { 285 | int fd; 286 | int res; 287 | (void) fi; 288 | FILE *file, *tempfile; 289 | const char *file_path = get_path(fpath); 290 | file = fopen(file_path, "r"); 291 | tempfile = tmpfile(); 292 | if (file == NULL || tempfile == NULL) { 293 | fprintf(stderr, "Failed to open file or create temp file.\n"); 294 | return -errno; 295 | } 296 | // Check if file is encrypted 297 | fd = is_encrypted(file_path) ? 0 : -1; 298 | if (do_crypt(file, tempfile, fd, ENC_PARAMS->key) == 0) { 299 | return -errno; 300 | } 301 | fflush(tempfile); 302 | fseek(tempfile, offset, SEEK_SET); 303 | res = fread(buf, 1, size, tempfile); 304 | if (res == -1) { 305 | res = -errno; 306 | } 307 | fclose(tempfile); 308 | fclose(file); 309 | return res; 310 | } 311 | 312 | static int xmp_write(const char *fpath, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { 313 | int fd; 314 | int res; 315 | (void) fi; 316 | FILE *file, *tempfile; 317 | int tempfile_desc; 318 | const char *file_path = get_path(fpath); 319 | file = fopen(file_path, "r+"); 320 | tempfile = tmpfile(); 321 | tempfile_desc = fileno(tempfile); 322 | if (file == NULL || tempfile == NULL) { 323 | fprintf(stderr, "Failed to open file or create temp file.\n"); 324 | return -errno; 325 | } 326 | if (xmp_access(fpath, R_OK) == 0 && size > 0) { 327 | fd = is_encrypted(file_path) ? 0 : -1; 328 | if (do_crypt(file, tempfile, fd, ENC_PARAMS->key) == 0) { 329 | return --errno; 330 | } 331 | rewind(file); 332 | rewind(tempfile); 333 | } 334 | res = pwrite(tempfile_desc, buf, size, offset); 335 | if (res == -1) { 336 | res = -errno; 337 | } 338 | fd = is_encrypted(file_path) ? 0 : -1; 339 | if (do_crypt(tempfile, file, fd, ENC_PARAMS->key) == 0) { 340 | return -errno; 341 | } 342 | fclose(tempfile); 343 | fclose(file); 344 | return res; 345 | } 346 | 347 | static int xmp_statfs(const char *fpath, struct statvfs *stbuf) { 348 | char *path = get_path(fpath); 349 | int res; 350 | res = statvfs(path, stbuf); 351 | if (res == -1) { 352 | return -errno; 353 | } 354 | return 0; 355 | } 356 | 357 | int add_encrypted_attr(const char *path) { 358 | int ret; 359 | int setxattr_ret; 360 | setxattr_ret = setxattr(path, "user.enc", "true", (sizeof(char)*5), 0); 361 | ret = setxattr_ret == 0; 362 | return ret; 363 | } 364 | 365 | static int xmp_create(const char* fpath, mode_t mode, struct fuse_file_info* fi) { 366 | char *path = get_path(fpath); 367 | (void) fi; 368 | int res; 369 | res = creat(path, mode); 370 | if (res == -1) { 371 | return -errno; 372 | } 373 | close(res); 374 | if (!add_encrypted_attr(path)) { 375 | return -errno; 376 | } 377 | return 0; 378 | } 379 | 380 | static int xmp_release(const char *fpath, struct fuse_file_info *fi) { 381 | /* Just a stub. This method is optional and can safely be left 382 | unimplemented */ 383 | (void) fpath; 384 | (void) fi; 385 | return 0; 386 | } 387 | 388 | static int xmp_fsync(const char *fpath, int isdatasync, struct fuse_file_info *fi) { 389 | /* Just a stub. This method is optional and can safely be left 390 | unimplemented */ 391 | 392 | (void) fpath; 393 | (void) isdatasync; 394 | (void) fi; 395 | return 0; 396 | } 397 | 398 | #ifdef HAVE_SETXATTR 399 | static int xmp_setxattr(const char *fpath, const char *name, const char *value, size_t size, int flags) { 400 | char *path = get_path(fpath); 401 | int res = lsetxattr(path, name, value, size, flags); 402 | if (res == -1) { 403 | return -errno; 404 | } 405 | return 0; 406 | } 407 | 408 | static int xmp_getxattr(const char *fpath, const char *name, char *value, size_t size) { 409 | char *path = get_path(fpath); 410 | int res = lgetxattr(path, name, value, size); 411 | if (res == -1) { 412 | return -errno; 413 | } 414 | return res; 415 | } 416 | 417 | static int xmp_listxattr(const char *fpath, char *list, size_t size) { 418 | char *path = get_path(fpath); 419 | int res = llistxattr(path, list, size); 420 | if (res == -1) { 421 | return -errno; 422 | } 423 | return res; 424 | } 425 | 426 | static int xmp_removexattr(const char *fpath, const char *name) { 427 | char *path = get_path(fpath); 428 | int res = lremovexattr(path, name); 429 | if (res == -1) { 430 | return -errno; 431 | } 432 | return 0; 433 | } 434 | #endif /* HAVE_SETXATTR */ 435 | 436 | static struct fuse_operations xmp_oper = { 437 | .getattr = xmp_getattr, 438 | .access = xmp_access, 439 | .readlink = xmp_readlink, 440 | .readdir = xmp_readdir, 441 | .mknod = xmp_mknod, 442 | .mkdir = xmp_mkdir, 443 | .symlink = xmp_symlink, 444 | .unlink = xmp_unlink, 445 | .rmdir = xmp_rmdir, 446 | .rename = xmp_rename, 447 | .link = xmp_link, 448 | .chmod = xmp_chmod, 449 | .chown = xmp_chown, 450 | .truncate = xmp_truncate, 451 | .utimens = xmp_utimens, 452 | .open = xmp_open, 453 | .read = xmp_read, 454 | .write = xmp_write, 455 | .statfs = xmp_statfs, 456 | .create = xmp_create, 457 | .release = xmp_release, 458 | .fsync = xmp_fsync, 459 | #ifdef HAVE_SETXATTR 460 | .setxattr = xmp_setxattr, 461 | .getxattr = xmp_getxattr, 462 | .listxattr = xmp_listxattr, 463 | .removexattr = xmp_removexattr, 464 | #endif 465 | }; 466 | 467 | int main(int argc, char *argv[]) { 468 | // ./pa5-encfs . 469 | umask(0); 470 | if (argc < 4) { 471 | // not enough args 472 | fprintf(stderr, "Not enough arguments.\n"); 473 | fprintf(stderr, "Usage: pa5-encfs \n"); 474 | return 1; 475 | } 476 | EncryptionParams* enc_params = NULL; 477 | enc_params = malloc(sizeof(EncryptionParams)); 478 | if (enc_params == NULL) { 479 | fprintf(stderr, "Memory allocation error.\n"); 480 | return 1; 481 | } 482 | // 0 (1:key) (2:mirror) (3:mount) 483 | enc_params->key = strdup(argv[1]); 484 | enc_params->dir = strdup(argv[2]); 485 | // Hack 486 | // leave arg0 unchanged 487 | argv[1] = argv[3]; 488 | argv[2] = NULL; 489 | argv[3] = NULL; 490 | return fuse_main(argc - 2, argv, &xmp_oper, enc_params); 491 | } 492 | -------------------------------------------------------------------------------- /Labs/Lab5/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | --------------------------------------------------------------------------------