diff --git a/file-api.tex b/file-api.tex index 48197e2..53fa84b 100644 --- a/file-api.tex +++ b/file-api.tex @@ -5,7 +5,7 @@ \begin{slide} \sltitle{File API} \begin{itemize} -\item before working with a file, it must be first open via +\item before working with a file, it must be first opened via \funnm{open}() or \funnm{creat}() \item open files are accessible via \emph{file descriptors}, numbered from 0. More descriptors can share the same file opening (read/write mode, position). @@ -112,12 +112,12 @@ current mask that can be changed via a shell command \texttt{umask} -- those bits in \emph{mode}, also set in the process umask, are nullified. The default umask value is typically (and historically) \texttt{022}. We recommend -you to always set it to \texttt{077} in your profile script. Never do that for +that you always set it to \texttt{077} in your profile script. Never do that for root though otherwise you will end up with a system in a non-supported configuration -- installed software will not be possible to run by non-privileged users, what worked before may stop working, etc. \item If the \emph{mode} argument is required and not specified, you get -whatever is on the stack. Both flags and the mode are stored in the system file +whatever is on the stack. Both flags and mode are stored in the system file table, see page \pageref{OPENFILETABLES}. \item Macros for use with \emph{mode} can be usually found in the manual page for \texttt{chmod(2)}, and you can find them also in the \texttt{stat.h} header @@ -142,8 +142,8 @@ as historically, implementations used 0 for the read-only flag. The standard defines that only one of those three flags may be used. \item Is is possible to open and create a file for writing so that writing is -disallowed by its mode. It will work for that file opening but any other file -opening for writing will fail. +disallowed by its mode. It will work for the initial file opening but any subsequent +attempts to write will fail. \item You need write permission to use \texttt{O\_TRUNC}. \item The behavior of \texttt{O\_EXCL} without using \texttt{O\_CREAT} at the same is undefined. @@ -179,10 +179,10 @@ \label{CREAT} \begin{itemize} -\item The \texttt{open} call allows to open a regular file, a device, or a named +\item The \texttt{open} call allows opening of a regular file, device, or named pipe. However, it (and \texttt{creat} as well) can only create a regular file, so you need the other two calls for non-regular files. -\item The test of a file existence using the flag \texttt{O\_EXCL} and its +\item The test of a file's existence using the flag \texttt{O\_EXCL} and its subsequent creation if it did not exist, is an atomic operation. You can use that for lock files but only with the \texttt{open} call, not \texttt{creat}. \item You need extra privileges to create device special files (e.g. to be a @@ -223,7 +223,7 @@ \setlength{\itemsep}{0.8\itemsep} \item For any Unix system, a file is just a sequence of bytes without any inner structure. -\item \emsl{Behavior of \texttt{read} and \texttt{write} depends on the type of +\item The \emsl{behavior of \texttt{read} and \texttt{write} depends on the type of the file} (regular, device, pipe, or socket) and whether the file is in a blocking or non-blocking mode (flag \texttt{O\_NONBLOCK} on file opening, see page \pageref{O_NONBLOCK}). @@ -236,7 +236,7 @@ \texttt{read} will block unless some data gets available, a non-blocking \texttt{read} returns -1 and sets \texttt{errno} to \texttt{EAGAIN}. \item \texttt{write} returns a non-zero number of bytes less than \emph{nbyte} -if less then \emph{nbyte} bytes can fit the file (e.g. disk full), if the call +if less then \emph{nbyte} bytes can fit into the file (e.g. disk full), if the call was interrupted by a signal, or if \verb#O_NONBLOCK# was set and only part of the data fits into a pipe, socket, or a device; without \verb#O_NONBLOCK# the call will block until all the data can be written. If nothing can be @@ -268,9 +268,9 @@ \begin{itemize} \item releases \texttt{fildes}, if it was the last descriptor for a file opening, closes the file -\item if number of links is 0, the file data is released -\item if the last pipe descriptor is closed, remaining data is lost -\item on a process termination, implicit \texttt{close} is called on all +\item if the number of links is 0, the file data is released +\item if the last pipe descriptor is closed, any remaining data is lost +\item on process termination, an implicit \texttt{close} is called on all descriptors \end{itemize} \end{slide} @@ -391,8 +391,8 @@ \item When writing to a pipe without a consumer (i.e. the producer opened the pipe when there was at least one existing consumer), the kernel will send the producer a signal \texttt{SIGPIPE} (``broken pipe''). See the following -example. For simplicity, we are using an unnamed pipe but that does not matter -as it would have behaved in the same manner. The \texttt{date(1)} command never +example. For simplicity, we are using an unnamed pipe but a named pipe +would behave in the same manner. The \texttt{date(1)} command never reads anything from its standard input so it is guaranteed that the producer, \texttt{dd(1)}, will be writing to a pipe without a consumer. If a process is killed by a signal, the shell provides a signal number added to 128 as its @@ -409,17 +409,17 @@ \item When opening a pipe for writing only with \texttt{O\_NONBLOCK} and without an existing consumer, the call returns -1 and \texttt{errno} is set to -\texttt{ENXIO}. This asymmetry to opening a pipe for reading in a non-blocking +\texttt{ENXIO}. This asymmetry in opening a pipe for reading in non-blocking mode is due to the fact that it is not desirable to have data in a pipe that may not be read in a short period of time. The Unix system does not allow for -storing pipe data for arbitrary length of time. Without the +storing pipe data for an arbitrary length of time. Without the \texttt{O\_NONBLOCK} flag, the process will block while waiting for a consumer. -By asymmetry we mean that the system does not mind to keep consumers without +By asymmetry, we mean that the system allows consumers without producers but it tries to avoid writers without existing readers. \item If you want to create a process that sits on a named pipe and processes data from producers, you need to open it with the flag \texttt{O\_RDWR} even -that you do not intend to write it. If you do not use the flag, you might end -up with \texttt{read} returning 0 after all producers, perhaps temporarily only, +if you do not intend to write to it. If you do not use the flag, you might end +up with \texttt{read} returning 0 after all producers, perhaps only temporarily, disappear, which could be solved by busy waiting. A much better solution would be to use the \texttt{select} call, see page \pageref{SELECT}. \item Writing data of length \texttt{PIPE\_BUF} bytes or less @@ -486,9 +486,9 @@ \begin{itemize} \item \label{LSEEK} The first byte is at position 0. If it makes sense, you may -use a negative number for setting \emph{offset}. Example: +use a negative number for setting the \emph{offset}. Example: \example{read/lseek.c}. -\item If it legal to move beyond the end of the file. If data is written there, +\item It is legal to move beyond the end of the file. If data is written there, the file size will be set accordingly, the ``holes'' will be read as zeros. Note that just changing the file position will not increase the file size. \item You can get the file size via \texttt{lseek(fildes, 0, SEEK\_END)}. @@ -496,19 +496,19 @@ position from the beginning of a file, setting the position to the end of a file, and getting the current file position (0 with \texttt{SEEK\_CUR}). \item There is no I/O involved when calling \texttt{lseek}. -\item You can obviously use \texttt{lseek} not only for subsequent calls +\item You can obviously use \texttt{lseek} not only for subsequent calls to \texttt{read} and \texttt{write} but also for another call to \texttt{lseek}. \item \label{BIG_FILE} Beware of files with holes as it may lead to problems with backing up the data. Example: \example{read/big-file.c} demonstrates that -moving a sparse file may end up in the actual storage data occupation increase. -It greatly depends on the system you run, what an archiving utility is used, and -their versions. Some utilities provide means to preserve holes, for example, +moving a sparse file may end up in an actual storage data occupation increase. +It greatly depends on the system you run, what archiving utility is used, and +their versions. Some utilities provide the means to preserve holes, for example, \texttt{dd} with \texttt{conv=sparse}, \texttt{tar} with \texttt{-S}, \texttt{rsync} with \texttt{--sparse}, etc. \item Beware of confusing the parameters. The second line below looks OK but the arguments are in reversed order. What is more, \texttt{SEEK\_SET} is defined as 0 and \texttt{SEEK\_CUR} is 1, so the file position is not moved -which is not by itself a disastrous thing, and makes it more difficult to find +which is not by itself a disastrous thing, which makes it more difficult to find it: \begin{verbatim} @@ -529,13 +529,13 @@ \item causes the regular file to be truncated to a size of precisely \emph{length} bytes. \item if the file was larger than \emph{length}, the extra data is lost -\item if the file previously was shorter, it is extended, and the extended part +\item if the file was previously shorter, it is extended, and the extended part reads as null bytes \end{itemize} \end{slide} \begin{itemize} -\item To truncate the file when opening it can be achieved via using the +\item Truncating the file when opening it can be achieved via the \texttt{O\_TRUNC} flag in \texttt{open}, see page \pageref{OPEN}. \end{itemize} @@ -605,13 +605,13 @@ \texttt{>>}. \item \label{REDIRECT} Another example of \texttt{dup} use will be provided when we start working with pipes. The first redirection example from the slide -(without \texttt{stderr}) is in \example{read/redirect.c}. The call -\texttt{execl} in that example replaces the current process image with the -program passed as the first argument. We got ahead of ourselves here though, we +(without \texttt{stderr}) is in \example{read/redirect.c}. In that example, the +\texttt{execl} call replaces the current process image with the +program passed in the first argument. We got ahead of ourselves here though, we will learn about the \texttt{exec} calls on page \pageref{EXEC}. \item To fully understand how redirection works it is good to draw the file -descriptor table for each step and where the slots point to. For example, for -the \nth{2} example in the slide, we have the initial state, after +descriptor table for each step and where the slots point to. In +the \nth{2} example in the slide above, we have the initial state, after \texttt{close(1)} and \texttt{open("out", ...)}, and the final state, as follows: @@ -626,7 +626,7 @@ \end{verbatim} \item You need to pay attention to the state of descriptors. The \nth{2} example -will not work if the descriptor 0 is already closed, as +above will not work if the descriptor 0 is already closed, as \texttt{open} returns 0 (the first available descriptor) and \texttt{dup} fails while trying to duplicate an already closed descriptor. Possible solutions: @@ -765,7 +765,7 @@ data itself, neither the filename as the file data can be accesses through several different hard links and those hardlinks are in the data of directories. In other words, metadata is data about the actual file data. -\item Metadata can be read even when the process has not rights to read the file +\item Metadata can be read even when the process has no rights to read the file data. \item These functions do not provide file descriptor flags or flags from the system file table. These functions are about file information as stored on some @@ -773,7 +773,7 @@ \item \texttt{st\_ctime} is not the creation time but the change time -- the last modification of the inode. \item The UNIX norm does not specify the ordering of the \texttt{struct stat} -members, neither it prohibits adding new. +members, nor does it prohibit adding new ones. \item \label{STAT} Example: \example{stat/stat.c} \item You can call \texttt{fstat} on file descriptors 0,1,2 as well. Unless redirected before, you will get information on the underlying terminal device diff --git a/intro.tex b/intro.tex index d2a330d..233f853 100644 --- a/intro.tex +++ b/intro.tex @@ -2214,17 +2214,17 @@ \begin{itemize} \item If all long options have the short variant set in \texttt{val}, the behavior of \texttt{getopt\_long} is compatible with that of \texttt{getopt}. -\item It is possible to specify the value of a long option also with a space +\item It is also possible to specify the value of a long option with a space (for example \texttt{--color~green}). \item If \texttt{flag} is set, \texttt{getopt\_long} returns 0, which makes -these long options without short variant processed in single branch of +these long options without the short variant get processed in a single branch of \texttt{case}. \item There is also \texttt{getopt\_long\_only}, which allows long options -to begin with single dash (\texttt{-option}). +to begin with a single dash (\texttt{-option}). \item The \texttt{getopt\_long} function is possible to use in two ways. The first way is that each long option has a corresponding short variant --- this way it is possible to introduce long options to existing program -in \emsl{getopt compatible} way. The second way makes it possible to have +-- this way it is possible to introduce long options to existing programs +in a \emsl{getopt compatible} way. The second way makes it possible to have independent long options. In this case the function always returns 0 (non-compatible with \texttt{getopt}) and the \texttt{*flag} variable is set to \texttt{val}. @@ -2245,9 +2245,9 @@ ]]]) \begin{itemize} \item \texttt{optstring} contains short options, -\texttt{longopts} contains address of array of structures for long options +\texttt{longopts} contains the address of an array of structures for long options (last record contains all zeroes) -\item if the function hits a long option, it returns corresponding +\item if the function hits a long option, it returns the corresponding \texttt{val} or zero (if \texttt{flag} was not \texttt{NULL}), otherwise the behavior is the same as \texttt{getopt}. \item it will also put the index of the found option in \texttt{longopts} @@ -2309,31 +2309,31 @@ \begin{itemize} \item This scheme is taken from [Bach86]. It emphasizes two central terms of the system model in UNIX -- files and processes. -\emsl{In modern Unixes it looks differently however for the time being +\emsl{In modern Unixes it looks different but for the time being such model will suffice.} -\item UNIX differentiates two modes of CPU: \emph{user mode} and -\emph{kernel mode}. In user mode there the privileged intructions are not +\item UNIX differentiates between two modes of CPU: \emph{user mode} and +\emph{kernel mode}. In user mode the privileged intructions are not available (e.g. memory mapping, I/O, interrupt masking). These modes have to be supported by the hardware (CPU). \item The processes usually spend most of the time running in user mode. -They enter kernel mode either by using synchronous interrupt (trap) for -calling kernel services or asynchronously (clock, I/O). In kernel mode +They enter kernel mode either by using a synchronous interrupt (trap) for +calling kernel services or asynchronously (clock, I/O). In kernel mode, the exceptional states are handled (page fault, memory protection failure, unknown instruction etc.). Some special tasks are handled by system processes running in kernel mode all the time. -\item Classic UNIX kernel is monolithic. Originally it was necessary to +\item The classic UNIX kernel is monolithic. Originally it was necessary to regenerate the kernel (i.e. compile from source code and link) whenever some kernel parameter had to be changed or add a device driver. In modern implementations it is possible to set many kernel parameters dynamically using system utilities. Also, many Unix systems extend kernel services by using \emph{loadable kernel modules}. For example FreeBSD 5.4-RELEASE has 392 such modules. -\item There are two ways how to handle peripheral devices: -\emph{block devices} and \emph{character / raw devices}. Block devices (e.g. -disk drives) pass the data through \emph{buffers} in blocks, character devices +\item There are two ways to handle peripheral devices: +\emph{block devices} and \emph{character/raw devices}. Block devices (e.g. +disk drives) pass the data through \emph{buffers} in blocks; character devices (e.g. terminals) make it possible to work with individual bytes and do not use buffering. -\item \emsl{The kernel is not individual process}, rather it is part of each +\item \emsl{The kernel is not an individual process}, rather it is part of each user process. When kernel is executing, it is usually user space performing some action in kernel mode. \end{itemize} @@ -2344,14 +2344,14 @@ \begin{slide} \sltitle{Processes, threads, program} \begin{itemize} -\item \emsl{process} is system object characterized by its context, +\item a \emsl{process} is a system object characterized by its context, identified by a unique number (\emsl{process ID}, \emsl{PID}); in other words \uv{code and data in memory} -\item \emsl{thread} is system object, that exists inside a process and -is characterized by its state. All threads within single process share +\item a \emsl{thread} is a system object that exists inside a process and +is characterized by its state. All threads within a single process share the same memory area sans registers and stack; \uv{line of execution}, \uv{what is running} -\item \emsl{program} ... file with precisely defined format that contains +\item a \emsl{program} is a file with a precisely defined format that contains instructions, data and service information needed for execution; \uv{executable file on disk} \end{itemize} @@ -2364,25 +2364,25 @@ \end{slide} \begin{itemize} -\item The \emsl{\emph{context}} is memory are of process, register contents and -kernel data structures relevant to given process. +\item The \emsl{\emph{context}} is the memory of a process, register contents and +the kernel data structures relevant to that process. \item In other words -- the context of a process is its state. When the system is executing the process, one says that it runs in the process context. The classic kernel handles interrupts in the context of interrupted process. -\item The threads were introduced to UNIX later, originally there were just +\item The threads were introduced to UNIX later - originally there were just processes that from today's perspective had only single thread. The possibility -to use multiple threads was introduced because it was shown that it is +of using multiple threads was introduced because it was shown that it is beneficial to have multiple lines of execution within the same process on -common shared data. -\item The memory areas of processes are isolated between each other however +commonly shared data. +\item The memory areas of processes are isolated between each other, however processes can communicate or explicitly share memory. \item While processes are kernel entities, threads can be partially or fully -implemented as user libraries. In the latter case this means that the kernel +implemented as user libraries. In the latter case, this means that the kernel does not have to support threading at all. Threads have smaller overhead than processes. \item A system process that is running for the whole time and provides some system services (\texttt{inetd}, \texttt{cron}, \texttt{sendmail}\dots) is -called \emph{daemon}. BSD system mascot is not a devil but daemon. +called a \emph{daemon}. BSD system mascot is not a devil but a daemon. \end{itemize} %%%%% @@ -2390,13 +2390,13 @@ \begin{slide} \sltitle{kernel, modes, interrupts/traps (classic UNIX)} \begin{itemize} -\item the processes typically run in user mode -\item a system call will cause switch to kernel mode +\item processes typically run in user mode +\item a system call will cause a switch to kernel mode \item a process has one stack for each mode -\item kernel is part of each user process, it is not a standalone process(es) -\item switching to different process is called \emph{context switch} +\item the kernel is part of each user process, it is not a standalone process(es) +\item switching to different process is called \emph{context switching} \item interrupt handling is performed in the context of interrupted process -\item classic kernel is non-preemptive +\item the classic kernel is non-preemptive \end{itemize} \end{slide} @@ -2406,17 +2406,17 @@ \item The transition between user and kernel mode is not a context switch -- the process is still running in the same context. \item The interrupted process is not necessarily the one that caused it. -\item In kernel mode a process can access kernel memory that is not accessible -from user mode. Likewise it can execute privileged instructions that would -otherwise cause error in user mode (like state register manipulations). -\item Interrupt routine cannot block because it would block the process; -process can block only on its own. Moder Unixes use interrupt threads, +\item In kernel mode, a process can access kernel memory that is not accessible +from user mode. Likewise, it can execute privileged instructions that would +otherwise cause errors in user mode (like state register manipulations). +\item An interrupt routine cannot block because it would block the process; +a process can only block on its own. Modern Unixes use interrupt threads, in their context the drivers \emsl{can} block. -\item The fact that classic UNIX kernel is non-preemptive means that +\item The fact that the classic UNIX kernel is non-preemptive means that \emsl{one process cannot block another process}. \item An interrupt can come while handling another interrupt. If its priority is higher, it is accepted by the CPU. The sequence of accepted interrupts is -saved in \emph{interrupt context stack}. +saved in an \emph{interrupt context stack}. \item \emsl{Modern kernels are very different in terms of interrupt handling, kernel preemption, etc.} \end{itemize} @@ -2436,27 +2436,27 @@ \end{slide} \begin{itemize} -\item If a Unix process requires to perform system task, it will pass the +\item If a Unix process is required to perform a system task, it will pass the control to the kernel using a system call. The kernel is code shared between -all processes however accessible only to those processes that are running in +all processes but accessible only to those processes that are running in kernel mode. The kernel is therefore not a standalone privileged process, -it is still running in the context of a process (one that requested system -service via system call or such that was running when interrupt came). +it is still running in the context of a process (one that requested a system +service via a system call or that was running when an interrupt came). \item Inter-process communication in UNIX is achieved using system calls, it is therefore handled by the kernel. \item There can be system processes called \emph{kernel threads}, that are running exclusively in kernel mode. The majority of system processes run in user -mode and differ from the rest in that they have elevated privileges. +mode differ from the rest in that they have elevated privileges. The process scheduler switches between processes and makes it possible to run multiple processes simultaneously even on single processor system. Multi-processor systems enable true parallelism of processes and threads (it is possible for a thread to migrate between processors based on scheduling). \item In distributed operating systems the kernel is in the form of microkernel, -i.e. provides only the very basic services like processor programming, memory +i.e. it provides only the very basic services like processor programming, memory allocation and inter-process communication. Upper system services that are part -of kernel in UNIX (e.g. file system access) are implemented as special processes -(servers) running in user mode. The kernel passes the request of user process to -relevant server that can be running on different network node. +of the kernel in UNIX (e.g. file system access) are implemented as special processes +(servers) running in user mode. The kernel passes the request of a user process to a +relevant server that can be running on a different network node. \item There are many microkernels today, e.g. Minix (unix-like system) or HURD that runs above the Mach micro-kernel. \end{itemize} @@ -2466,19 +2466,19 @@ \begin{slide} \sltitle{System calls, functions} \begin{itemize} -\item In UNIX a distinction is made of \emsl{system calls} and \emsl{library +\item In UNIX a distinction is made between \emsl{system calls} and \emsl{library functions}. This division is maintained in man pages: section \emsl{2} contains system call man pages and section \emsl{3} library functions. \begin{itemize} \item library functions are executed in user mode, just like the rest of the program's code. - \item system calls also have the form of a function. However given function + \item system calls also have the form of a function. However, a given function only processes arguments and passes the control to the kernel using synchronous interrupt instruction. Once it returns from the kernel, - it will adjust the result and returns it to the caller. + it will adjust the result and return it to the caller. \end{itemize} \item this distinction is not made in the standard -- from programmer's -perspective it does not \emph{usually} matter if given function is processed +perspective it does not \emph{usually} matter if a given function is processed by a library or kernel. \end{itemize} \end{slide} @@ -2486,13 +2486,13 @@ \begin{itemize} \item The transition from userland to kernel can be costly; if the program executes lot of syscalls, it can have a negative effect on its performance. -\emsl{Library function can but does not have to perform some system calls, +\emsl{A library function can but does not have to perform some system calls, however it always does some non-trivial work in user mode.} -\item It is possible to perform system call directly in assembler. +\item It is possible to perform system calls directly in the assembler. \item The kernel API is defined w.r.t. function calls of the standard library, not w.r.t. interrupt level and data structures used by these functions when passing control to the kernel. The mechanism of switching between user and -kernel mode can differ not only depending on hardware platform but also between +kernel mode can differ not only depending on the hardware platform but also between different versions of the same system on the same hardware. \end{itemize} @@ -2515,13 +2515,13 @@ \item \texttt{!= NULL} \dots{} success \item \texttt{== NULL} \dots{} failure \end{itemize} -\item after failed syscall the error code is stored in global variable +\item after a failed syscall, the error code is stored in global variable \texttt{extern int \funnm{errno};} -\item successful syscall never changes \texttt{errno} ! It is therefore +\item a successful syscall never changes \texttt{errno}! It is therefore necessary to test the return value first and then check \texttt{errno}. -\item error message depending on the \texttt{errno} value can be printed with\\ +\item error messages depending on the \texttt{errno} value can be printed with\\ \texttt{void \funnm{perror}(const char *\emph{s});} -\item textual representation for given value is returned by\\ +\item textual representation for a given value is returned by\\ \texttt{char *\funnm{strerror}(int \emph{errnum});} \end{itemize} \end{slide} @@ -2529,29 +2529,29 @@ %%%%% \begin{itemize} -\item \label{ERRNO} In Solaris \texttt{errno} is in reality defined in -\texttt{libc} as a dereferenced pointer to integer (specific to userland thread) -and the value is set right after the instruction for system call. -For example on i386 architecture the \texttt{errno} value is stored in the +\item \label{ERRNO} In Solaris, \texttt{errno} is in reality defined in +\texttt{libc} as a dereferenced pointer to an integer (specific to a userland thread) +and the value is set right after the instruction for the system call. +For example, on the i386 architecture the \texttt{errno} value is stored in the \texttt{eax} register after the return from the syscall (after the -\texttt{sysenter} instruction is executed). Before the instruction the register +\texttt{sysenter} instruction is executed). Before the instruction, the register held the system call number. It is therefore the \texttt{libc} library that is responsible for the program to see the correct \texttt{errno} value. \item The POSIX thread functions (\texttt{pthread\_*}) do not set -\texttt{errno}, rather they return either zero or error code. -\item For some calls it the \texttt{-1} is semantically valid. To use such +\texttt{errno}, rather they return either zero or an error code. +\item For some calls, the value \texttt{-1} is semantically valid. To use such functions, it is necessary to set \texttt{errno~=~0} before the call and check whether the value changed after the call. E.g. the \texttt{strtol} function -returns 0 on failure, which is valid value even for valid result -(and $-1$ is also valid result value). -\item It is therefore necessary to always read the man page for appropriate +returns 0 on failure, which can also be a valid value in some cases +(and $-1$ is also a valid result value). +\item It is therefore necessary to always read the appropriate man page for the system call or library function. -\item Note that the failure or functions from \texttt{stdio.h} it is necessary +\item Note that from the failure return values from \texttt{stdio.h}, it is necessary to test using\\ \texttt{int \funnm{ferror}(FILE *\emph{stream})}, because it is not otherwise possible to distinguish between an error and end of stream. Considering we are not using these functions in the lecture (except -\texttt{printf} and \texttt{fprintf} for \texttt{stdout}, resp. +\texttt{printf} and \texttt{fprintf} for \texttt{stdout} and \texttt{stderr}), you should not need it. \end{itemize}