Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

COMP 3000 (WINTER 2022) OPERATING SYSTEMS ASSIGNMENT 2

Please submit the answers to the following questions in Brightspace by the due time indicated in the submission entry. There are 20 points in total (weight: 0.25).

Submit your answers as a gzipped tarball "username-comp3000-assign2.tar.gz" (where username is your MyCarletonOne username). Do NOT just submit a file of another format (e.g., txt or zip) by renaming it        to .tar.gz. Unlike tutorials, assignments are graded for the correctness of the answers.

The tarball you submit must contain the following:


1.  A plaintext file containing your solutions to all questions, including explanations.

2.  A README.txt file listing the contents of your submission as well as any information the TAs should know when grading your assignment. Without this file, grading will be based on the TA’s                   understanding.

3.  For each question, where applicable, a C file for your modified version of the provided source code. This should include all required changes for that question. This way, you can avoid something         wrong with one question affecting another question.

4.  Diff files showing the modifications, by comparing each submitted C file above and the original: for example, diff -c 3000test.c 3000test_modifiedQ1.c > Q1.diff. Avoid moving around or changing existing code (unless necessary) which may be distracting.



You only need to submit code for the following questions:

Part 1: Q1 (3000test) and Part 2: Q7 (3000userlogin.patched).

You can use this command to create the tarball: tar zcvf username-comp3000-assign2.tar.gz your_assignment_directory. **Don’t forget to include your plaintext file!!**

No other formats will be accepted. Submitting in another format will likely result in your assignment not being graded and you receiving no marks for this assignment. In particular, do not submit an MS Word,                   OpenOffice, or PDF file as your answers document!

Empty or corrupted tarballs may be given a grade of zero, so please double check your submission by

downloading and extracting it.

Don't forget to include what outside resources you used to complete each of your answers, including other    students, and web resources. You do not need to list help from the instructor, TA, or information found in the textbook or man pages.

Use of any outside resources verbatim as your answer (like copy-paste or quotation) is not allowed, and will be treated as unauthorized collaboration (and reported as plagiarism).

Please do NOT post assignment solutions on MS Teams or Brightspace (or other platforms not used in the course such as Discord) or it will be penalized. Moreover, posting the assignment questions to any external forums/websites is NOT permitted and will also be penalized/reported.


Questions  part 1 [14]


The following questions (where applicable) will be based on the original3000test.c

in Tutorial 5:

Note: in this part, always use “ls -ls” to see both the logical size and the physical size. Calling an external program explicitly in the code is not allowed.

To save you from having to read the superblock to determine filesystem block size, you can find it out using “sudo blockdev –getbsz [block_device_name]” and hardcode it in your code.

1.  Make your 3000test output one of the following lines, when the provided file is a symbolic link (dereferenced) or a regular file:

- Sparse file: YES; Internal fragmentation: YES

- Sparse file: NO; Internal fragmentation: YES

- Sparse file: NO; Internal fragmentation: NO

- Sparse file: YES; Internal fragmentation: NO This must reflect the actual situation of the file [3].

Definition: a sparse file is a file with “holes”, which means not all data blocks are allocated (blocks  containing just 0’s will not be allocated until written to; the corresponding data pointers in the inode just point to NULL). Internal fragmentation in the context of this course refers to wasted/unused      space (not covered by the file’s actual size) within allocated blocks.

[1.5] Explain why you made this code change, with a reasoning like “why checking this can lead to the conclusion of this YES/NO”.

You can make sure it works by testing it with a few files of the four cases above. Hint: make good use of the C struct in Tutorial 5.

2.  You may have noticed in Tutorial 3 that, the C struct dirent also contains the file type                 information d_type (see man readdir) such as DT_REG for regular files. This way, you can avoid reading the actual file (i.e., its inode by stat()) unless needed, which may improve performance    when processing a large number of files (not our case though) in the same directory. For instance,   you will only touch the actual file when you want to search for ‘a’ in it but not before that. [2] State     the main reason why it will not be a good idea to use d_type in place of st_mode in 3000test from the perspective of programming/implementation.

Note that both fields will be available for our ext4 (or neither otherwise) so no compatibility issues.

3.  If you want to avoid the call to mmap() (line 59) without affecting the current functionality (i.e.,        3000test still does all it can do now), 1) [2] what standard C functions can you use instead?            (mention all needed) 2) what will likely be a design challenge (or a value to determine) to trade off between performance and space? [1] Please be specific.

From here, we can see the advantages of mmap() which we will discuss further later in the course. The size of the file to read cannot be predetermined. You do not need to implement it this time (no  code submission; just written answers).

4.  Let’s generate a file filled with all 1’s using this command:

LC_CTYPE=C tr '\0' '\377' < /dev/zero | dd of=myfile count=200 (‘\377’ is 0xff in octal)

Of course, myfile cannot be made sparse as it does not contain any 0’s. Next, make a few copies of it using the cp command:

for i in {1..3}; do cp myfile "myfile$i"; done

The next few commands will add a chunk of 0’s in different ways: 

dd if=/dev/zero of=myfile1 dd if=/dev/zero of=myfile2 dd if=/dev/zero of=myfile3

conv=notrunc count=6        conv=notrunc count=8 seek=1 conv=notrunc count=8

Then, try to optimize them using this command:



for i in {1..3}; do cp "myfile$i" "myfile$i.processed" --sparse=always; done

You can use either ls -ls or your updated 3000test in Q1 to check, and you will see although we have injected 0’s to all three files, only myfile3.processed was optimized (smaller physical size).      [3] Explain why myfile1.processed and myfile2.processed did not get optimized (no change), by      showing some calculation with numbers.

5.  In the question above, we used a translator to convert the 0’s from /dev/zero to 1’s. [0.5] Explain

why we cannot simply use echo -n -e "\xff" | dd of=myfile count=200 to create a file  filled with 1’s of any size (the 200 is an example). Nevertheless, inspired by Q4, you can still adjust it to make it work. Give it a try [1] (no need to consider performance).

You should not change the commands used here, i.e., echo and dd, or introduce new commands.


Questions  part 2 [6]


The following questions (where applicable) will be based on the patched version of 3000userlogin.cin the posted explanation of Tutorial 4. The diff file is alsoherefor  your reference.

Keep in mind each time you update the code, you will need to follow the same steps in Tutorial 4 to make it “setuid root”. You can put them in a script or a Makefile if you want to.

Calling an external program explicitly in the code is not allowed.

 

6.  [1] Without “setuid root”, why does 3000userlogin.patched report “Could not find user” even for a valid existing user, instead of “Failed to change to gid” as was seen with the original 3000userlogin? Make sure to mention the root cause.

7.  You may have noticed the behavior of 3000userlogin resembles that of the su command to some     extent (although still different). The main difference is whether the whole environment is reinitialized for the specified user (login) or just temporarily running something on its behalf (UID/GID switch).     We can implement both in a way similar to busybox.

In the directory where you have built and prepared the downloaded 3000userlogin.patched: ln -s 3000userlogin.patched login

ln -s 3000userlogin.patched su

Then you can simply use ./su someuser and ./login someuser

You should also be able to use it anywhere else by specifying the full pathname, e.g., /home/student/su someuser.

Make changes to 3000userlogin.patched to support this [3].

Requirements:

- When called as ./login, the current behavior of 3000userlogin.patched must be preserved.

- When called as ./su, 1) the current directory should not be changed; 2) only $HOME, $USER and $SHELL are set to that of “someuser”, other environment variables preserved; 3) run $SHELL     (instead of the hardcoded /bin/bash) as the new shell; 4) obviously UID and GID should be set   for “someuser”.

In both cases, you should be able to return using exit like before.

8.   [1] In the question above, explain why you do not need to follow the same steps to “setuid root” the two links ( ./su and ./login) but they still work.

9.  Can we use ln without “-s” to achieve the same purpose? [1] Why not (if NO) or what will be the implications (if YES)? (note the mark is not for a YES/NO answer but the explanation)