# Systemy Operacyjne - lista 4
## Zadanie 1

```c=
void tty_curpos(int fd, int *x, int *y) {
struct termios ts, ots; // terminos - struktura zawierajaca atrybuty terminala
tcgetattr(fd, &ts); // pobieramy aktualne ustawienia terminala
memcpy(&ots, &ts, sizeof(struct termios)); // kopiujemy je do ots
ts.c_lflag &= ~(ECHO | ICANON); // wyłączamy echo i icanon
ts.c_cflag &= ~CREAD; // wyłączamy: Allow input to be received
tcsetattr(fd, TCSADRAIN, &ts); // ustawiamy nowe ustawienia terminala oraz odpalamy TCSADRAIN - zmiany zostaną ustawione dopiero po wypluciu wszystkiego z outputu
/* How many characters in the input queue. */
int m = 0;
/* TODO: Need to figure out some other way to do it on MacOS / FreeBSD. */
#ifdef LINUX
ioctl(fd, TIOCINQ, &m); // Get the number of bytes in the input buffer.
#endif
/* Read them all. */
char discarded[m]; // tworzytmy tablice bajtow do zdiscardowania
m = Read(fd, discarded, m); // czytamy wszystko co jest na inpucie
//#define CPR() CSI "6n" /* Cursor Position Report */
//Reports the cursor position (CPR) by transmitting ESC[n;mR, where n is the row and m is the column.
Write(fd, CPR(), sizeof(CPR())); //wypisujemy pozycje kursora
char buf[20]; // tworzymy buffor 20B
int n = Read(fd, buf, 19); // czytamy do 19B
buf[n] = '\0'; // dodajemy na koniec 1B znak konca lini
ts.c_lflag |= ICANON; // odpalamy tryb kanoniczny
tcsetattr(fd, TCSADRAIN, &ts); // ustawiamy terminal z trybem kanonicznym i znowu z TCSADRAIN
for (int i = 0; i < m; i++) // petla po kazdym znaku ktory byl w inpucie
ioctl(fd, TIOCSTI, discarded + i); // Insert the given byte in the input queue. - dodajemy spowrotem to co zdiscardowalismy
tcsetattr(fd, TCSADRAIN, &ots); // przywracamy stare ustawienia terminala
sscanf(buf, "\033[%d;%dR", x, y); // wpisujemy do x - row y - column -> pozycje kursora
}
```
___TCGETS___ - Equivalent to tcgetattr(fd, argp).
Pobiera ustawienia terminala terminos
___TCSETSW___ - Equivalent to tcsetattr(fd, TCSADRAIN, argp).
Ustawia nowe ustawienia terminala ale dopiero po wypluciu wszystkiego z outputu
## Zadanie 2

***sctript(1)*** - The script(1) program that is supplied with most UNIX systems makes a copy in a file of everything that is input and output during a terminal session. The program does this by placing itself between the terminal and a new invocation of our login shell.
Since our keystrokes are normally echoed by that line discipline module, the script file also contains our input. The script file won’t contain any passwords that we enter, however, since passwords aren’t echoed.

```\r``` = CR (Carriage Return) → Used as a new line character in Mac OS before X
```\n``` = LF (Line Feed) → Used as a new line character in Unix/Mac OS X
```\r\n``` = CR + LF → Used as a new line character in Windows
***ONLCR*** - map NL to CR-NL (ala CRMOD)
***INLCR*** - map CR to NL (ala CRMOD) ^M mozna pokazac
```
16140 write(3, "\r", 1) = 1
16141 <... read resumed>"ls\n", 8192) = 3
16140 read(3, "\r\n", 8192) = 2
```

## Zadanie 3

***Łączenie procesów rurami***
```
22953 pipe2([3, 4], 0) = 0
...
22953 <... pipe2 resumed>[4, 5], 0) = 0
```
***Przekierowanie standardowego wyjścia do pliku***
```
21974 openat(AT_FDCWD, "cnt", O_WRONLY|O_CREAT|O_TRUNC, 0666 <unfinished ...>
21972 <... openat resumed>) = 3
21974 <... openat resumed>) = 3
21974 close(1) = 0
21974 dup2(3, 1) = 1
```
***W jakiej kolejności będą wywołały następujące wywołania systemowe***
1. pipe2(2) -> wywoływane przez dash'a
2. clone(2) -> wywoływane przez dash'a
4. dup2(2) -> wywoływane przez procesy z 2.
5. close(2) -> wywoływane przez wszystkie procesu
pipe(2) - nie ma xd
## Zadanie 4

***Kiedy powłoka tworzy nową grupe procesów***
```
22953 setpgid(22964, 22964 <unfinished ...>
```
***Jak umieszta tam procesy realizujące potok***
```
22953 setpgid(22964, 22964 <unfinished ...>
...
22953 setpgid(22965, 22964 <unfinished ...>
...
22953 setpgid(22966, 22964 <unfinished ...>
```
***
A process may not change the process group ID of one of its children after that
child has performed an exec(). Violation of this rule results in the error EACCES. The rationale for this constraint is that it could confuse a program if its process group ID were changed after it had commenced.For each process in the job, either the parent or the child could use setpgid() to change the process group ID of the child. However, because the scheduling of the parent and child is indeterminate after a fork() (Section 24.4), we can’t rely on the parent changing the child’s process group ID before the child does an exec(); nor can we rely on the child changing its process group ID before the parent tries to send any job-control signals to it. (Dependence on either one of these behaviors would result in a race condition.) Therefore, job-control shells are programmed so that the parent and the child process both call setpgid() to change the child’s process group ID to the same value immediately after a fork(), and the parent ignores any occurrence of the EACCES error on the setpgid() call.
***Kiedy powłoka ustala grupę pierwszoplanową przy pomocy ioctl(2)?***
```
22953 ioctl(10, TIOCSPGRP, [22953]) = 0
22964 ioctl(10, TIOCSPGRP, [22964] <unfinished ...>
```
***Na jakiej podstawie powłoka wyznacza kod wyjścia potoku***
Kod wyjścia jest to kod wyjścia ostatniego polecenia
## Zadanie 5

***Czemu nie można czytać i modyfikować katalogów przy pomocy wywołań read(2) i write(2)***
Ponieważ read i write nie są do tego dostosowane - read i write czytają/zapisują bajty a katalog jest listą rekordów i my chcemy zawsze odczytywać/zapisywać cały rekord
***Rekord katalogu*** - [**Nazwa Pliku** - **INODE**]
***Jakim wywołaniem systemowym można wczytać rekord katalogu***
```c=
readdir()
getdirentries() // tez mozna ale nie jest kompatybilne z kazdym systemem linuxowym to wyzej lepsze
```
***Dlaczego zawartość katalogu nie jest posortowana?***
Bo zawartość katalogu to rekordy?
***Z czego wynika podana liczba dowiązań?***
Liczba twardych dowiązań wynika z ilości rekordów katalogów które wskazują na ten sam i-node
## Zadanie 6

Musimy dodać flage O_EXCL ponieważ, jeżeli nie ma tej flagi to pomiędzy sprawdzeniem warunku a otwarciem pliku mozemy zmienic path przez co zostanie otwarty jakis wrazliwy plik np kiedys /etc/passwd ponieważ Open z O_CREAT jezeli plik istnieje to go po prostu otwiera a połączenie OCREAT|O_EXCL wywala błąd jeżeli plik istnieje :)
```c=
return Open(path, O_CREAT|O_EXCL|O_WRONLY, 0700) > 0;
```
## Zadanie 7

***innocent.c***
```c=
char buff[1024];
const int buf_size = 1024;
char link[buf_size];
char path[buf_size];
int read_count;
for(long i = 0; i < max_fd; i++){
// sprawdzamy czy i jest poprawnym fc
if(lseek(i, 0, SEEK_SET) >= 0){
// do link wczytujemy link do pliku z odpowiedniego fd[i]
snprintf(link, buf_size, "/proc/self/fd/%ld", i);
int path_len;
// wczytujemy do path sciezke
if ((path_len = Readlink(link, path, buf_size)) < 0) {
fprintf(stderr, "Readlink failure!");
exit(1);
}
// dodajemy na koncu znak nowej linij
path[path_len] = '\0';
dprintf(out, "File descriptor %ld is '%s' file!\n", i, path);
// przepisujemy plik
while((read_count = read(i, &buff, 1024)) > 0){
Write(out, &buff, read_count);
}
}
}
```
***leaky.c***
```c=
// ustawiamy flage FD_CLOEXEC fd_2
// FC_CLOEXEC zamyka file descriptor po poprawnym zakonczeniu execve(2)
fcntl(fd_2, F_SETFD, FD_CLOEXEC)
```
> File descriptor flags The following commands manipulate the flags associated with a file descriptor. Currently, only one such flag is defined: FD_CLOEXEC, the close-on-exec flag. If the FD_CLOEXEC bit is set, the file descriptor will automatically be closed during a successful execve(2). (If the execve(2) fails, the file descriptor is left open.) If the FD_CLOEXEC bit is not set, the file descriptor will remain open across an execve(2).
## Zadanie 8


1112 * 512 = 569 344
***Czemu liczba używanych bloków jest mniejsza od tej wynikającej z objętości pliku z pola st_size?***
Ponieważ plik moze miec dziury które są wypełnione zerami.
***Czemu jest większa od liczby faktycznie używanych bloków zgłaszanych przez mkholes***
Ponieważ stat liczy blok jako 512B
> blkcnt_t st_blocks; /* Number of 512B blocks allocated */