1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/UnixFile.html
2025-01-28 10:11:14 +01:00

1090 lines
No EOL
88 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>2.6. The UNIX File Abstraction &mdash; Computer Systems Fundamentals</title>
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
<style>
.underline { text-decoration: underline; }
</style>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.4.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": {
scale: "80"
}
});
</script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
<link rel="next" title="7. Events and Signals" href="EventsSignals.html" />
<link rel="prev" title="5. Process Life Cycle" href="ProcessCycle.html" />
</head><body>
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
<!-- Show a navbar toggler on mobile -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="defaultNavbars">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle jmu-gold rounded" href="UnixFile.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
<a class="dropdown-item" tabindex="-1" href="UnixFile.html#"><b>Chapter 1</b></a>
<a class="dropdown-item" href="IntroConcSysOverview.html">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;1.7. Extended Example: State Model Implementation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
<a class="dropdown-item" href="ProcessesOverview.html">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;2.8. Extended Example: Listing Files with Processes</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
<a class="dropdown-item" href="IPCOverview.html">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
<a class="dropdown-item" href="SocketsOverview.html">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;4.8. Extended Example: CGI Web Server</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
<a class="dropdown-item" href="InternetOverview.html">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;5.8. Extended Example: DNS client</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
<a class="dropdown-item" href="ThreadsOverview.html">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;6.8. Extended Example: Concurrent Prime Number Search</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
<a class="dropdown-item" href="SynchOverview.html">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;7.8. Extended Example: Event Log File</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
<a class="dropdown-item" href="SynchProblemsOverview.html">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;8.7. Extended Example: Parallel Modular Exponentiation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
<a class="dropdown-item" href="ParallelDistributedOverview.html">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;9.8. Extended Example: Blockchain Proof-of-Work</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Appendix A</b></a>
<a class="dropdown-item" href="CLangOverview.html">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;A.9. Files</a>
</div>
</li>
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/UnixFile.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="ProcessCycle.html">2.5. Process Life Cycle</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="EventsSignals.html">2.7. Events and Signals</a>&#160;&#160;»
</div>
<br />
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
<script type="text/javascript" src="_static/js/config.js"></script>
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
<div class="container">
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "UnixFile";ODSA.SETTINGS.MODULE_LONG_NAME = "The UNIX File Abstraction";ODSA.SETTINGS.MODULE_CHAPTER = "Processes and OS Basics"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:25"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="the-unix-file-abstraction">
<h1>2.6. The UNIX File Abstraction<a class="headerlink" href="UnixFile.html#the-unix-file-abstraction" title="Permalink to this headline"></a></h1>
<p>When multiple processes exist on a single machine, they rely on virtual memory to create the
illusion that they have sole access to the CPU; the context switch mechanism prevents one process
from accessing another processs register values, stack, heap, etc. However, processes ultimately do
not have sole access to the entire machine. There are many resources, such as a network interface,
storage devices, user input devices, and so on, that must be shared with other processes on the same
machine. As such, processes act as a unit of ownership for instances of access to these resources.</p>
<p>The <a class="reference internal" href="Glossary.html#term-unix-file-abstraction"><span class="xref std std-term">UNIX file abstraction</span></a>, which is widely used in modern OS design, provides a uniform
interface to these various shared resources. This abstraction relies on two features: <strong>a file is a
sequence of bytes</strong> and <strong>everything is a file</strong>. It is important to emphasize that this definition
is different from the common usage of the term “file,” which is typically associated with persistent
data storage. The key differences between this common usage and the UNIX file abstraction are as follows:</p>
<blockquote>
<div><ul class="simple">
<li>Arbitrary or bidirectional access to a file is not necessarily possible. In some cases, once a
byte has been read from the file, that byte no longer exists in the file; there is no way to seek
to a previous position in such files. Similarly, sequential access of the bytes in order may be
required, with no way to skip ahead.</li>
<li>Files may not have names or persistent storage. Some files (such as those described in Chapter 3
for <a class="reference internal" href="Glossary.html#term-interprocess-communication"><span class="xref std std-term">interprocess communication</span></a>, commonly referred to as IPC) exist solely as in-memory
constructs at run-time, identified only by an integer <a class="reference internal" href="Glossary.html#term-file-descriptor"><span class="xref std std-term">file descriptor</span></a>. Other files (such as
<code class="docutils literal notranslate"><span class="pre">/dev/random</span></code> on UNIX and Linux systems) exist solely as an abstract interface to a hardware
component or generate data at run-time on demand.</li>
<li>Files do not necessarily have structure or typing. Readers are likely family with persistent files
that can be distinguished by a file extension. For instance, a file with the <code class="docutils literal notranslate"><span class="pre">.pdf</span></code> extension has
a different internal structure than one with a <code class="docutils literal notranslate"><span class="pre">.png</span></code> extension; programs that read or write
these files must make sure that the bytes adhere to a pre-defined semantic structure. However, in
the UNIX file abstraction, this pre-defined structure does not exist; a file is <cite>just</cite> a sequence of bytes.</li>
</ul>
</div></blockquote>
<p>By removing so much contextual information about files, this abstraction might seem to lose much of
its meaning or utility. On the contrary, this abstraction greatly simplifies the work of dealing
with a variety of resources; there are certain operations (creating, deleting, opening, closing,
reading, writing) that are common to the lifecycle of all files. The UNIX file abstraction provides
a single, consistent interface for these operations, thus eliminating much of the complexity of
supporting many such resources.</p>
<div class="section" id="basic-file-access">
<h2>2.6.1. Basic File Access<a class="headerlink" href="UnixFile.html#basic-file-access" title="Permalink to this headline"></a></h2>
<p>The most basic operations for working with files are creating and opening them. For files that can
be identified with named locations in the file system directory structure (such as <code class="docutils literal notranslate"><span class="pre">/dev/random</span></code>,
<code class="docutils literal notranslate"><span class="pre">/usr/bin/cksum</span></code>, or <code class="docutils literal notranslate"><span class="pre">/home/csf/movies.csv</span></code>), we can use the <code class="docutils literal notranslate"><span class="pre">open()</span></code> function. The first
parameter is the path to the file; this path can be an <em>absolute path</em> (such as
<code class="docutils literal notranslate"><span class="pre">/dev/random</span></code>) or a <em>relative path</em> (such as <code class="docutils literal notranslate"><span class="pre">../src/main.c</span></code>) that describes the location
relative to the current working directory. If the file is successfully opened, the return value from
<code class="docutils literal notranslate"><span class="pre">open()</span></code> is the file descriptor, a non-negative integer value that other functions use to identify
the file. This value should typically be greater than 2, as the default behavior is to open three
files when a process is created: 0 (<code class="docutils literal notranslate"><span class="pre">STDIN_FILENO</span></code>) for standard input (such as reading from the
command prompt), 1 (<code class="docutils literal notranslate"><span class="pre">STDOUT_FILENO</span></code>) for standard output (such as writing out to the screen), and
2 (<code class="docutils literal notranslate"><span class="pre">STDERR_FILENO</span></code>) for standard error (also writing out to the screen).</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;fcntl.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">open(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">int</span> <span class="pre">oflag,</span> <span class="pre">...);</span></code></dt>
<dd>Open or create a file for reading or writing.</dd>
</dl>
</div>
<p>The second parameter (<code class="docutils literal notranslate"><span class="pre">oflag</span></code>) specifies how the file will be accessed by the current process.
<a class="reference external" href="UnixFile.html#tbl2-2">Table 2.2</a> shows the flags that may be passed as a bit-mask to <code class="docutils literal notranslate"><span class="pre">open()</span></code>. Note that these flags do
not necessarily align with the common notion of file permissions; a file that is accessible for both
reading and writing may be opened in read-only mode (<code class="docutils literal notranslate"><span class="pre">O_RDONLY</span></code>). However, if the file permissions
do not allow the requested access, <code class="docutils literal notranslate"><span class="pre">open()</span></code> will return -1.</p>
<center>
<div class="row-10">
<table class="table table-bordered">
<thead class="jmu-dark-purple-bg text-light">
<tr>
<th class="py-0 center">Permission</th>
<th class="py-0 center">Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-0"><code>O_RDONLY</code></td>
<td class="py-0">Open for reading only</td>
</tr>
<tr>
<td class="py-0"><code>O_WRONLY</code></td>
<td class="py-0">Open for writing only</td>
</tr>
<tr>
<td class="py-0"><code>O_RDWR</code></td>
<td class="py-0">Open for reading and writing</td>
</tr>
<tr>
<td class="py-0"><code>O_NONBLOCK</code></td>
<td class="py-0">Do not block on opening while waiting for data</td>
</tr>
<tr>
<td class="py-0"><code>O_CREAT</code></td>
<td class="py-0">Create the file if it does not exist; requires passing <code>mode_t</code> argument</td>
</tr>
<tr>
<td class="py-0"><code>O_TRUNC</code></td>
<td class="py-0">Truncate to size 0</td>
</tr>
<tr>
<td class="py-0"><code>O_EXCL</code></td>
<td class="py-0">Error if <code>O_CREAT</code> and the file exists</td>
</tr>
</tbody>
</table>
<p>Table 2.2: Flags for opening files</p>
</div>
</center><p>For the common usage of the term “file,” the <code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> flag is the least intuitive in <a class="reference external" href="UnixFile.html#tbl2-2">Table
2.2</a>, as this flag is normally used for other purposes. Specifically, this flag plays an important
role in IPC and network programming. When using a file to communicate with other processes (either
on the same machine or across the network), the default behavior for reading is for processes to
<a class="reference internal" href="Glossary.html#term-blocking-i-o"><span class="xref std std-term">block</span></a> (pause) until the data has been received from the sender. The <code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> flag
changes this behavior so that reading will immediately fail and the process can move on to other
work instead of waiting.</p>
<p><a class="reference external" href="UnixFile.html#cl2-12">Code Listing 2.12</a> illustrates how the flags can be combined as a bitmask using the bitwise-or
(<code class="docutils literal notranslate"><span class="pre">|</span></code>). In this case, the file is also being created (<code class="docutils literal notranslate"><span class="pre">O_CREAT</span></code>) with a size of 0 bytes initially
(<code class="docutils literal notranslate"><span class="pre">O_TRUNC</span></code>) and the current process will have write-only access (<code class="docutils literal notranslate"><span class="pre">O_WRONLY</span></code>). This file will be
persistent and stored in the file system with 644 permissions (6 = read and write for the owner of
the file, 4 = read-only for the associated group and others); as such, the file could later be
opened in read-write mode. Note that this third parameter (<code class="docutils literal notranslate"><span class="pre">mode</span></code>) is required when creating a new
file, but is ignored at other times.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-12"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
2
3
4
5
6
7
8</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.12:</span>
<span class="cm"> Creating a new (empty) file that is ready for writing</span>
<span class="cm"> */</span>
<span class="cm">/* This will create an empty file */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">path</span> <span class="o">=</span> <span class="s">&quot;data.log&quot;</span><span class="p">;</span>
<span class="kt">mode_t</span> <span class="n">mode</span> <span class="o">=</span> <span class="mo">0644</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_TRUNC</span> <span class="o">|</span> <span class="n">O_WRONLY</span><span class="p">,</span> <span class="n">mode</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>Once the file has been opened, it can be read from. The <code class="docutils literal notranslate"><span class="pre">read()</span></code> function takes three parameters:
the file descriptor, the address of a buffer in memory to read the bytes into, and the maximum
number of bytes to read. <a class="footnote-reference" href="UnixFile.html#f15" id="id2">[1]</a> The value returned from <code class="docutils literal notranslate"><span class="pre">read()</span></code> indicates the actual number of
bytes successfully read, which may be fewer than the <code class="docutils literal notranslate"><span class="pre">nbyte</span></code> parameter. (Calling <code class="docutils literal notranslate"><span class="pre">read()</span></code> with
<code class="docutils literal notranslate"><span class="pre">nbyte</span></code> set to 100 on a file that only contains 10 bytes of data will return 10, not 100.)
Finally, when the process is finished working with a file, the <code class="docutils literal notranslate"><span class="pre">close()</span></code> function will release any
associated resources in the kernel or the C library data that have been allocated for this process.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;unistd.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">ssize_t</span> <span class="pre">read(int</span> <span class="pre">fildes,</span> <span class="pre">void</span> <span class="pre">*buf,</span> <span class="pre">size_t</span> <span class="pre">nbyte);</span></code></dt>
<dd>Read up to nbyte bytes from a file into the buffer identified by buf.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">close(int</span> <span class="pre">fildes);</span></code></dt>
<dd>Deletes a file descriptor.</dd>
</dl>
</div>
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
<p>There are several key aspects of working with files that are easy to underestimate. First and
foremost is the importance of using a correct value for the <code class="docutils literal notranslate"><span class="pre">nbyte</span></code> parameter of <code class="docutils literal notranslate"><span class="pre">read()</span></code>. This
parameter always indicates the maximum number of bytes to read and it should never indicate more
than the size of the allocated buffer pointer. <a class="reference internal" href="Glossary.html#term-buffer-overflow"><span class="xref std std-term">Buffer overflows</span></a> are some
of the most dangerous and persistent sources of software vulnerabilities, and passing an incorrect
parameter to <code class="docutils literal notranslate"><span class="pre">read()</span></code> is a common culprit. Consider the following example:</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
2
3
4</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Allocate a buffer of 2 bytes */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">));</span>
<span class="cm">/* WRONG: This reads MORE THAN 2 bytes into the buffer */</span>
<span class="n">read</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
</pre></div>
</td></tr></table></div>
<p>The problem here is a misunderstanding of the <code class="docutils literal notranslate"><span class="pre">sizeof()</span></code> keyword, which returns the size of the
specified parameter. The misunderstanding is that <code class="docutils literal notranslate"><span class="pre">sizeof(buffer)</span></code> returns the size of a pointer
variable (8 bytes on a 64-bit system), not the size of the dynamically allocated buffer on the
heap. (Contrast this with lines 5 and 6 in <a class="reference external" href="UnixFile.html#cl2-13">Code Listing 2.13</a> below.) As such, this code is trying
to read up to 8 bytes of data into a buffer than can only hold 2 bytes. The result is that
<code class="docutils literal notranslate"><span class="pre">read()</span></code> will simply copy the additional 6 bytes into the memory <cite>after</cite> the end of the buffer,
potentially corrupting other data.</p>
<p>There are other frequent, though less serious, problems with using files. One (which is also in the
example above) is to call <code class="docutils literal notranslate"><span class="pre">read()</span></code> without checking its return value; programmers often assume
that the number of bytes read is the same as the number of bytes requested, which is not
necessarily true. To illustrate this, consider the possibility of calling <code class="docutils literal notranslate"><span class="pre">read()</span></code> on a file that
has been opened in <code class="docutils literal notranslate"><span class="pre">O_WRONLY</span></code> mode; <code class="docutils literal notranslate"><span class="pre">read()</span></code> would return -1 to indicate the operation failed.
Another problem is failing to call <code class="docutils literal notranslate"><span class="pre">close()</span></code>; this causes memory leaks, as allocated data is not
freed up appropriately. On the other hand, another problem can arise when a file descriptor is used
after the file has been closed; this can cause future reads to fail or (potentially even worse) to
read from the wrong file.</p>
</div>
<p><a class="reference external" href="UnixFile.html#cl2-13">Code Listing 2.13</a> illustrates how to open, read from, and close a file. In this example, we are
reading from a special file known as <code class="docutils literal notranslate"><span class="pre">/dev/random</span></code>. This file can be used to generate a sequence
of random numbers one byte at a time; every time this code runs, the result should be different.
Note that the file is closed on line 13, but the data is not used by the program until line 17. This
is not a problem, as the data was read into the processs memory; that is, the <code class="docutils literal notranslate"><span class="pre">read()</span></code> operation
has made a copy of the data on the stack, so access to the file is no longer necessary.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-13"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.13:</span>
<span class="cm"> Reading 10 random numbers using the /dev/random file</span>
<span class="cm"> */</span>
<span class="kt">uint8_t</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span> <span class="c1">// space allocated automatically on the stack</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="cm">/* /dev/random is a special device file that produces an</span>
<span class="cm"> unending stream of random numbers */</span>
<span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;/dev/random&quot;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
<span class="kt">ssize_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Read %zd bytes of random data:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">bytes</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot; %02&quot;</span> <span class="n">PRIx8</span><span class="p">,</span> <span class="n">buffer</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>Some files, particularly IPC and device interface files, require special handling when reading.
Recall that the default behavior for open files is to block until data is ready; this behavior is
undesirable when other productive work could be done. For instance, a web server that is blocking
while trying to read data from one client could be missing out on connection requests from other
clients. The <code class="docutils literal notranslate"><span class="pre">poll()</span></code> function provides a useful interface for avoiding this situation.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;poll.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">poll(struct</span> <span class="pre">pollfd</span> <span class="pre">fds[],</span> <span class="pre">nfds_t</span> <span class="pre">nfds,</span> <span class="pre">int</span> <span class="pre">timeout);</span></code></dt>
<dd>Examine an array of file descriptors to determine if some are ready for I/O.</dd>
</dl>
</div>
<p>The first argument to <code class="docutils literal notranslate"><span class="pre">poll()</span></code> consists of an array of <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">pollfd</span></code> instances, the second
parameter is the length of the array, and the <code class="docutils literal notranslate"><span class="pre">timeout</span></code> designates a maximum amount of time
(measured in milliseconds) to wait for input to be ready. The fields of the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">pollfd</span></code> are
shown below. For each <code class="docutils literal notranslate"><span class="pre">struct</span></code> in the array, the <code class="docutils literal notranslate"><span class="pre">fd</span></code> field designates a file descriptor to
monitor for input or output events, and the <code class="docutils literal notranslate"><span class="pre">events</span></code> field designates the events to wait for.
Typically, <code class="docutils literal notranslate"><span class="pre">events</span></code> is set to the constant <code class="docutils literal notranslate"><span class="pre">POLLIN</span></code> to indicate a check for the presence of
normal data that can be read without blocking. The <code class="docutils literal notranslate"><span class="pre">revents</span></code> field is set by the call to
<code class="docutils literal notranslate"><span class="pre">poll()</span></code>.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
2
3
4
5
6</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* defined in poll.h */</span>
<span class="k">struct</span> <span class="n">pollfd</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span> <span class="cm">/* file descriptor */</span>
<span class="kt">short</span> <span class="n">events</span><span class="p">;</span> <span class="cm">/* events to look for */</span>
<span class="kt">short</span> <span class="n">revents</span><span class="p">;</span> <span class="cm">/* events returned */</span>
<span class="p">};</span>
</pre></div>
</td></tr></table></div>
<p><a class="reference external" href="UnixFile.html#cl2-14">Code Listing 2.14</a> shows how to use <code class="docutils literal notranslate"><span class="pre">poll()</span></code> to check for available data. If <code class="docutils literal notranslate"><span class="pre">poll()</span></code> returns 0,
then the requested event (available input data) has not occurred before the timeout expired. The
<code class="docutils literal notranslate"><span class="pre">revents</span></code> field would be set to a value to indicate why the <code class="docutils literal notranslate"><span class="pre">poll()</span></code> failed. For instance,
<code class="docutils literal notranslate"><span class="pre">POLLHUP</span></code> indicates the device has been disconnected, <code class="docutils literal notranslate"><span class="pre">POLLNVAL</span></code> indicates the file descriptor
is not open, and <code class="docutils literal notranslate"><span class="pre">POLLERR</span></code> indicates an error has occurred with the device.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-14"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.14:</span>
<span class="cm"> Checking a file descriptor for available input data</span>
<span class="cm"> */</span>
<span class="cm">/* Set up a single pollfd for the file descriptor fd */</span>
<span class="k">struct</span> <span class="n">pollfd</span> <span class="n">fds</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="n">fds</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">fd</span> <span class="o">=</span> <span class="n">fd</span><span class="p">;</span>
<span class="n">fds</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">events</span> <span class="o">=</span> <span class="n">POLLIN</span><span class="p">;</span> <span class="c1">// Looking for input data</span>
<span class="k">if</span> <span class="p">(</span><span class="n">poll</span> <span class="p">(</span><span class="n">fds</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">// wait for 100 ms</span>
<span class="p">{</span>
<span class="cm">/* No data is available to be read */</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Poll failed: %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">fds</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">revents</span><span class="p">);</span>
<span class="cm">/* Close and exit if appropriate */</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="n">exit</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="working-with-files">
<h2>2.6.2. Working with Files<a class="headerlink" href="UnixFile.html#working-with-files" title="Permalink to this headline"></a></h2>
<p>In addition to reading, programs typically need to write to a file. The arguments to <code class="docutils literal notranslate"><span class="pre">write()</span></code> are
identical to those for <code class="docutils literal notranslate"><span class="pre">read()</span></code>. Unlike <code class="docutils literal notranslate"><span class="pre">read()</span></code>, there is not really a concern with buffer
overflow with <code class="docutils literal notranslate"><span class="pre">write()</span></code>, as data is being sent away from the current process; the kernel buffers
on the other end will prevent such errors. However, checking the return value from <code class="docutils literal notranslate"><span class="pre">write()</span></code> is as
important as it is with <code class="docutils literal notranslate"><span class="pre">read()</span></code> to make sure that all of the intended data was written
successfully; this is especially true when writing large pieces of data. <a class="reference external" href="UnixFile.html#cl2-15">Code Listing 2.15</a>
illustrates how to write to a file. Note that writing to the end of a persistent file will cause it
to grow. In this example, the file is created to be empty (<code class="docutils literal notranslate"><span class="pre">O_TRUNC</span></code>), but writing six bytes
creates a file of size six (the last byte is the null terminator <code class="docutils literal notranslate"><span class="pre">'\0'</span></code>).</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;unistd.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">ssize_t</span> <span class="pre">write(int</span> <span class="pre">fildes,</span> <span class="pre">const</span> <span class="pre">void</span> <span class="pre">*buf,</span> <span class="pre">size_t</span> <span class="pre">nbyte);</span></code></dt>
<dd>Write up to nbyte bytes from a buffer into the specified file.</dd>
</dl>
</div>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-15"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.15:</span>
<span class="cm"> Creating an empty file and writing to it</span>
<span class="cm"> */</span>
<span class="cm">/* Create an empty file with read and write permissions */</span>
<span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;blank&quot;</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_TRUNC</span><span class="p">,</span> <span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="cm">/* Open the file for writing (write will append) */</span>
<span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;blank&quot;</span><span class="p">,</span> <span class="n">O_WRONLY</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">write</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="cm">/* Read in what we just wrote */</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;blank&quot;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">read</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Contents: [%s]</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>If the file supports arbitrary accesses, the <code class="docutils literal notranslate"><span class="pre">lseek()</span></code> function will change the files internal
location information to a specified target. The <code class="docutils literal notranslate"><span class="pre">offset</span></code> can be specified as either a positive or
negative value. The <code class="docutils literal notranslate"><span class="pre">whence</span></code> parameter, which takes a limited number of possible values, plays an
important role in determining this location. If <code class="docutils literal notranslate"><span class="pre">whence</span></code> if set to <code class="docutils literal notranslate"><span class="pre">SEEK_SET</span></code>, then the
<code class="docutils literal notranslate"><span class="pre">offset</span></code> argument is the exact number of bytes into the file to use as the location. Setting
<code class="docutils literal notranslate"><span class="pre">whence</span></code> to <code class="docutils literal notranslate"><span class="pre">SEEK_CUR</span></code> will add the <code class="docutils literal notranslate"><span class="pre">offset</span></code> to the current location number; a negative
<code class="docutils literal notranslate"><span class="pre">offset</span></code> will seek backwards, while a positive value seeks forward. Lastly, setting <code class="docutils literal notranslate"><span class="pre">whence</span></code> to
<code class="docutils literal notranslate"><span class="pre">SEEK_END</span></code> will add the <code class="docutils literal notranslate"><span class="pre">offset</span></code> to the size of the file; using a negative offset moves the
location to the number of bytes before the end of the file. Whichever value is passed, the final
location must be positive. If the location is larger than the file size, performing a write at that
point will increase the file size accordingly. Any gap between the existing end of the file and the
new data will be filled with null bytes.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;unistd.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">off_t</span> <span class="pre">lseek(int</span> <span class="pre">fildes,</span> <span class="pre">off_t</span> <span class="pre">offset,</span> <span class="pre">int</span> <span class="pre">whence);</span></code></dt>
<dd>Reposition the offset of a file descriptor to a specified location.</dd>
</dl>
</div>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-16"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.16:</span>
<span class="cm"> Growing a file with lseek() and write()</span>
<span class="cm"> */</span>
<span class="cm">/* Open and jump to offset 10 (4 bytes after the end) */</span>
<span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;blank&quot;</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">);</span>
<span class="kt">off_t</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">lseek</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Offset is now %lld</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
<span class="cm">/* Write additional bytes, appending to the file */</span>
<span class="kt">size_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">write</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="s">&quot;goodbye&quot;</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Wrote %zd additional bytes</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>
<span class="cm">/* Now read all of the file into a buffer and print it.</span>
<span class="cm"> Note that the file only contains 18 bytes */</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">20</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="n">offset</span> <span class="o">=</span> <span class="n">lseek</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Offset is now %lld</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">read</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span> <span class="o">==</span> <span class="mi">18</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Contents:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;%02x &#39;%c&#39;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">buffer</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">buffer</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p><a class="reference external" href="UnixFile.html#cl2-16">Code Listing 2.16</a> shows the effect of using <code class="docutils literal notranslate"><span class="pre">lseek()</span></code> and <code class="docutils literal notranslate"><span class="pre">write()</span></code> on the file created by Code
Listing 2.15. The file initially contained six bytes (<code class="docutils literal notranslate"><span class="pre">'h'</span></code>, <code class="docutils literal notranslate"><span class="pre">'e'</span></code>, <code class="docutils literal notranslate"><span class="pre">'l'</span></code>, <code class="docutils literal notranslate"><span class="pre">'l'</span></code>, <code class="docutils literal notranslate"><span class="pre">'o'</span></code>,
<code class="docutils literal notranslate"><span class="pre">'\0'</span></code>). The seek on line 7 places the internal location to offset 10. The <code class="docutils literal notranslate"><span class="pre">write()</span></code> on line 11,
then, extends the file size to include the new data, as well as the padding of null bytes; the new
file size would then be 18 bytes. As such, the <code class="docutils literal notranslate"><span class="pre">read()</span></code> on line 20 requests 20 bytes but only gets
18. Printing the final file with <code class="docutils literal notranslate"><span class="pre">hexdump</span></code> shows the results:</p>
<div class="highlight-none border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span>00000000 68 65 6c 6c 6f 00 00 00 00 00 67 6f 6f 64 62 79 |hello.....goodby|
00000010 65 00 |e.|
00000012
</pre></div>
</div>
</div>
<div class="section" id="accessing-file-metadata">
<h2>2.6.3. Accessing File Metadata<a class="headerlink" href="UnixFile.html#accessing-file-metadata" title="Permalink to this headline"></a></h2>
<p>When working with files, it is often important to access <a class="reference internal" href="Glossary.html#term-metadata"><span class="xref std std-term">metadata</span></a> information about the
file rather than the contents about the file itself. For instance, when reading a persistent file
into memory from storage, knowing the files size is necessary for allocating memory for the buffer.
As another example, consider an <em>intrusion detection</em> program that is responsible for
monitoring a file system for security threats or attacks; this program might check for changes to
the associated permissions or the user ID that is considered the owner of the file.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;sys/stat.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fstat(int</span> <span class="pre">fildes,</span> <span class="pre">struct</span> <span class="pre">stat</span> <span class="pre">*buf);</span></code></dt>
<dd>Get status information about a file given an open file descriptor.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">stat(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">struct</span> <span class="pre">stat</span> <span class="pre">*buf);</span></code></dt>
<dd>Get status information about a file.</dd>
</dl>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">fstat()</span></code> and <code class="docutils literal notranslate"><span class="pre">stat()</span></code> functions provide an interface for accessing file metadata. Note that
<code class="docutils literal notranslate"><span class="pre">stat()</span></code> uses the path name of the file within the directory structure, which is appropriate for
the common notion of a file as persistent storage; however, <code class="docutils literal notranslate"><span class="pre">fstat()</span></code> works on any file
descriptor, which allows you to examine the metadata of any file, including unnamed IPC or device
files. Both functions take a pointer to a <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">stat</span></code>, writing the file metadata into this buffer.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* defined in sys/stat.h */</span>
<span class="k">struct</span> <span class="n">stat</span> <span class="p">{</span>
<span class="kt">dev_t</span> <span class="n">st_dev</span><span class="p">;</span> <span class="cm">/* device inode resides on */</span>
<span class="kt">ino_t</span> <span class="n">st_ino</span><span class="p">;</span> <span class="cm">/* inode&#39;s number */</span>
<span class="kt">mode_t</span> <span class="n">st_mode</span><span class="p">;</span> <span class="cm">/* inode protection mode */</span>
<span class="n">nlink_t</span> <span class="n">st_nlink</span><span class="p">;</span> <span class="cm">/* number of hard links to the file */</span>
<span class="kt">uid_t</span> <span class="n">st_uid</span><span class="p">;</span> <span class="cm">/* user-id of owner */</span>
<span class="kt">gid_t</span> <span class="n">st_gid</span><span class="p">;</span> <span class="cm">/* group-id of owner */</span>
<span class="kt">dev_t</span> <span class="n">st_rdev</span><span class="p">;</span> <span class="cm">/* device type, for special file inode */</span>
<span class="kt">off_t</span> <span class="n">st_size</span><span class="p">;</span> <span class="cm">/* file size, in bytes */</span>
<span class="cm">/* ... other fields depending on OS ... */</span>
<span class="p">};</span>
</pre></div>
</td></tr></table></div>
<p>This <code class="docutils literal notranslate"><span class="pre">struct</span></code> definition contains additional fields based on the particular operating system, but
the ones shown here are consistent across multiple platforms. A full discussion of all of these
fields is beyond the scope of this book, but a few of them are particularly important. To start,
consider the <code class="docutils literal notranslate"><span class="pre">st_ino</span></code> and <code class="docutils literal notranslate"><span class="pre">st_nlink</span></code> fields. Each file stored on typical storage device (USB
drive, hard drive, etc.) is uniquely identified by an <a class="reference internal" href="Glossary.html#term-inode"><span class="xref std std-term">inode</span></a>, an on-disk data structure that
contains the metadata; each inode is uniquely identified by an inode number (<code class="docutils literal notranslate"><span class="pre">st_ino</span></code>). However,
the file might have multiple human-readable names in the directory structure. These names
<em>links</em> (also called <em>hard links</em>) all point to the same file
contents; the <code class="docutils literal notranslate"><span class="pre">st_nlink</span></code> field indicates the number of links that exist to a single file. With
hard links, there is only one file; there are just multiple references to the same location. In
contrast a <em>symbolic link</em> is a distinct file that is not represented in the inode. See
Appendix A for a longer discussion of inodes and links.</p>
<p>Another key field of the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">stat</span></code> is the <code class="docutils literal notranslate"><span class="pre">st_mode</span></code> field. The most common use of this field
is to set permissions for accessing the file. These permissions include combinations of read, write,
and execute for the owner of the file (the user), the associated group, or everyone else. The
<code class="docutils literal notranslate"><span class="pre">st_mode</span></code> field also stores additional permissions and information about the file; for instance,
this field can be used to distinguish symbolic links, regular files, or directories. <a class="reference external" href="UnixFile.html#tbl2-3">Table 2.3</a> shows
the standard list of bitmask values that can be combined in the <code class="docutils literal notranslate"><span class="pre">st_mode</span></code> field.</p>
<center>
<div class="row">
<div class="col-6 align-top">
<table class="table table-bordered">
<thead class="jmu-dark-purple-bg text-light">
<tr>
<th class="py-0 center">Name</th>
<th class="py-0 center">Bitmask</th>
<th class="py-0 center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-0"><code>S_IRUSR</code></td>
<td class="py-0"><code>000400</code></td>
<td class="py-0">Read (user)</td>
</tr>
<tr>
<td class="py-0"><code>S_IWUSR</code></td>
<td class="py-0"><code>000200</code></td>
<td class="py-0">Write (user)</td>
</tr>
<tr>
<td class="py-0"><code>S_IXUSR</code></td>
<td class="py-0"><code>000100</code></td>
<td class="py-0">Execute (user)</td>
</tr>
<tr>
<td class="py-0"><code>S_IRGRP</code></td>
<td class="py-0"><code>000040</code></td>
<td class="py-0">Read (group)</td>
</tr>
<tr>
<td class="py-0"><code>S_IWGRP</code></td>
<td class="py-0"><code>000020</code></td>
<td class="py-0">Write (group)</td>
</tr>
<tr>
<td class="py-0"><code>S_IXGRP</code></td>
<td class="py-0"><code>000010</code></td>
<td class="py-0">Execute (group)</td>
</tr>
<tr>
<td class="py-0"><code>S_IROTH</code></td>
<td class="py-0"><code>000004</code></td>
<td class="py-0">Read (other)</td>
</tr>
<tr>
<td class="py-0"><code>S_IWOTH</code></td>
<td class="py-0"><code>000002</code></td>
<td class="py-0">Write (other)</td>
</tr>
<tr>
<td class="py-0"><code>S_IXOTH</code></td>
<td class="py-0"><code>000001</code></td>
<td class="py-0">Execute (other)</td>
</tr>
</tbody>
</table>
</div>
<div class="col-6 align-top">
<table class="table table-bordered">
<thead class="jmu-dark-purple-bg text-light">
<tr>
<th class="py-0 center">Name</th>
<th class="py-0 center">Bitmask</th>
<th class="py-0 center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-0"><code>S_IFIFO</code></td>
<td class="py-0"><code>010000</code></td>
<td class="py-0">Named pipe (IPC)</td>
</tr>
<tr>
<td class="py-0"><code>S_IFCHR</code></td>
<td class="py-0"><code>020000</code></td>
<td class="py-0">Character device (terminal)</td>
</tr>
<tr>
<td class="py-0"><code>S_IFDIR</code></td>
<td class="py-0"><code>040000</code></td>
<td class="py-0">Directory file type</td>
</tr>
<tr>
<td class="py-0"><code>S_IFBLK</code></td>
<td class="py-0"><code>006000</code></td>
<td class="py-0">Block device (disk drive)</td>
</tr>
<tr>
<td class="py-0"><code>S_IFREG</code></td>
<td class="py-0"><code>100000</code></td>
<td class="py-0">Regular file type</td>
</tr>
<tr>
<td class="py-0"><code>S_IFLNK</code></td>
<td class="py-0"><code>120000</code></td>
<td class="py-0">Symbolic link</td>
</tr>
<tr>
<td class="py-0"><code>S_IFSOCK</code></td>
<td class="py-0"><code>140000</code></td>
<td class="py-0">Socket (IPC, networks)</td>
</tr>
<tr>
<td class="py-0"><code>S_ISUID</code></td>
<td class="py-0"><code>004000</code></td>
<td class="py-0">Setuid (<code>SUID</code>) bit</td>
</tr>
<tr>
<td class="py-0"><code>S_ISGID</code></td>
<td class="py-0"><code>002000</code></td>
<td class="py-0">Setgid (<code>SGID</code>) bit</td>
</tr>
<tr>
<td class="py-0"><code>S_ISVTX</code></td>
<td class="py-0"><code>001000</code></td>
<td class="py-0">Sticky bit</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Table 2.3: Bitmasks used in the st_mode field</p>
</center><p>For example, the hello.c file above would have the bitmask <code class="docutils literal notranslate"><span class="pre">100644</span></code> (displayed as <code class="docutils literal notranslate"><span class="pre">-rw-r--r--</span></code>
by the <code class="docutils literal notranslate"><span class="pre">ls</span> <span class="pre">-l</span></code> command), as it is a regular file (<code class="docutils literal notranslate"><span class="pre">100000</span></code>) with read/write permissions for the
user and read for group and others. The symlink.c would have <code class="docutils literal notranslate"><span class="pre">st_mode</span></code> <code class="docutils literal notranslate"><span class="pre">120755</span></code> (displayed as
<code class="docutils literal notranslate"><span class="pre">lrwxr-xr-x</span></code>). Note that the first character in the displayed version indicates the type of file
(<code class="docutils literal notranslate"><span class="pre">-</span></code> for <code class="docutils literal notranslate"><span class="pre">S_IFREG</span></code>, <code class="docutils literal notranslate"><span class="pre">l</span></code> for <code class="docutils literal notranslate"><span class="pre">S_IFLNK</span></code>, <code class="docutils literal notranslate"><span class="pre">d</span></code> for <code class="docutils literal notranslate"><span class="pre">S_IFDIR</span></code>, and so on).</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Note.png"><img alt="Decorative note icon" src="_images/CSF-Images-Note.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Note</p><hr class="mt-1" />
<p>The <code class="docutils literal notranslate"><span class="pre">SUID</span></code>, <code class="docutils literal notranslate"><span class="pre">SGID</span></code>, and sticky bits have complex meanings and interpretations. One source of
their complexity is that <code class="docutils literal notranslate"><span class="pre">SUID</span></code> only affects executable regular files, the sticky bit (which is
mostly obsolete and has changed over time) only affects, and <code class="docutils literal notranslate"><span class="pre">SGID</span></code> affects both executables and
directories! These meanings can be summarized as follows:</p>
<blockquote>
<div><ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">SUID</span></code>: Processes created with this executable will inherit the user ID of the files owner,
rather than the user ID of the user executing the program.</li>
<li><code class="docutils literal notranslate"><span class="pre">SGID</span></code> (regular file): Processes created with this executable will inherit the group ID of the
files group, rather than the group ID of the user executing the program.</li>
<li><code class="docutils literal notranslate"><span class="pre">SGID</span></code> (directory): Files and subdirectories created in this directory will inherit the group ID
of this directory.</li>
<li>Sticky bit (modern usage): Files in this directory can only be deleted by the user who is considered the owner of the file.</li>
</ul>
</div></blockquote>
<p>When these bits are set on a file, <code class="docutils literal notranslate"><span class="pre">ls</span> <span class="pre">-l</span></code> displays them by overlaying them on top of the execute
bits in the permission field, using an <code class="docutils literal notranslate"><span class="pre">'s'</span></code> in the user field for <code class="docutils literal notranslate"><span class="pre">SUID</span></code>, <code class="docutils literal notranslate"><span class="pre">'s'</span></code> in the group
field for <code class="docutils literal notranslate"><span class="pre">SGID</span></code>, and <code class="docutils literal notranslate"><span class="pre">'t'</span></code> in the other field for the sticky bit; if the corresponding <code class="docutils literal notranslate"><span class="pre">'x'</span></code>
bit is present, a lower-case letter is used, while an upper-case letter indicates the <code class="docutils literal notranslate"><span class="pre">'x'</span></code> bit
is absent. For instance, <code class="docutils literal notranslate"><span class="pre">rwsr-x---</span></code> would indicate both <code class="docutils literal notranslate"><span class="pre">S_IXUSR</span></code> and <code class="docutils literal notranslate"><span class="pre">S_ISUID</span></code> are set;
<code class="docutils literal notranslate"><span class="pre">rw-r-Sr--</span></code> would mean that <code class="docutils literal notranslate"><span class="pre">S_IGUID</span></code> is set but <code class="docutils literal notranslate"><span class="pre">S_IXGRP</span></code> is not.</p>
</div>
<p><a class="reference external" href="UnixFile.html#cl2-17">Code Listing 2.17</a> illustrates how to use <code class="docutils literal notranslate"><span class="pre">fstat()</span></code> to investigate a files metadata. The address
of the local variable <code class="docutils literal notranslate"><span class="pre">info</span></code> is passed to <code class="docutils literal notranslate"><span class="pre">fstat()</span></code> to collect the metadata on line 9. Lines 13
15 are using the bitwise-and operator (<code class="docutils literal notranslate"><span class="pre">&amp;</span></code>) to determine if certain permission bits are set; the
result would be non-zero (true) if the bit is set but would be zero (false) if not. Lines 18 and 19
demonstrate a very common technique when reading in files. Line 19 uses the <code class="docutils literal notranslate"><span class="pre">st_size</span></code> field to
allocate the exact amount of space needed to read in the full file contents, then line 20 reads in
exactly that number of bytes. Once the file is read into memory, it can be accessed in a variety of
ways. Since this file is an ASCII-formatted CSV file, it can be manipulated just like a normal
string. Line 24 uses <code class="docutils literal notranslate"><span class="pre">strtok()</span></code> to split this string at the first instance of the newline
character (<code class="docutils literal notranslate"><span class="pre">'\n'</span></code>); line 25 can then print just that line as a string. This change only affects
the in-memory buffer, and it does not change the contents of the original file stored on disk.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-17"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.17:</span>
<span class="cm"> Using fstat() to determine the file size and read in the exact amount of data</span>
<span class="cm"> */</span>
<span class="cm">/* Open a CSV file and read its status information */</span>
<span class="k">struct</span> <span class="n">stat</span> <span class="n">info</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="s">&quot;movies.csv&quot;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fstat</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">info</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
<span class="cm">/* Check the file size and permissions */</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;File is %lld bytes in size</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">info</span><span class="p">.</span><span class="n">st_size</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Is file readable by user? %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">info</span><span class="p">.</span><span class="n">st_mode</span> <span class="o">&amp;</span> <span class="n">S_IRUSR</span> <span class="o">?</span> <span class="s">&quot;yes&quot;</span> <span class="o">:</span> <span class="s">&quot;no&quot;</span><span class="p">));</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Is file executable by user? %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">info</span><span class="p">.</span><span class="n">st_mode</span> <span class="o">&amp;</span> <span class="n">S_IXUSR</span> <span class="o">?</span> <span class="s">&quot;yes&quot;</span> <span class="o">:</span> <span class="s">&quot;no&quot;</span><span class="p">));</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Is this a directory? %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">info</span><span class="p">.</span><span class="n">st_mode</span> <span class="o">&amp;</span> <span class="n">S_IFDIR</span> <span class="o">?</span> <span class="s">&quot;yes&quot;</span> <span class="o">:</span> <span class="s">&quot;no&quot;</span><span class="p">));</span>
<span class="cm">/* Create a buffer that is the exact size of the file and</span>
<span class="cm"> read in the contents */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="n">info</span><span class="p">.</span><span class="n">st_size</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">));</span>
<span class="kt">ssize_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">info</span><span class="p">.</span><span class="n">st_size</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">bytes</span> <span class="o">==</span> <span class="n">info</span><span class="p">.</span><span class="n">st_size</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">line</span> <span class="o">=</span> <span class="n">strtok</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Here is the first line:</span><span class="se">\n</span><span class="s">%s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">line</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Note.png"><img alt="Decorative note icon" src="_images/CSF-Images-Note.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Note</p><hr class="mt-1" />
<p>The traditional UNIX permission structure—assigning permissions based only on the user, group, or
other—is inflexible and not well suited for many applications. For example, consider two user that
are collaborating on a project. These two users both need full permissions to read and write to a
file, but they do not want to make the file publicly accessible otherwise. Under the traditional
approach, a system administrator could create a group containing these two users; the users could
then set permissions based on the group ID. The problem is that each user can only be assigned to a
single group. If these users also have similar collaborations with different users on the same
system, they cannot use the same approach.</p>
<p>To fix this problem, many modern systems support <em>access control lists</em>
(ACLs). Using ACLs, users can grant or revoke permissions to other users on an individual basis. In
addition, ACLs allow the same user to be a member of multiple groups. Rather than using the
traditional ls and chmod commands to view and change permissions, ACLs use the <code class="docutils literal notranslate"><span class="pre">getfacl</span></code> and
<code class="docutils literal notranslate"><span class="pre">setfacl</span></code> commands. Consider the following example of these two commands.</p>
<div class="highlight-none border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span>$ getfacl team
# file: team
# owner: csf
# group: staff
user::rwx
user:alissa:rwx
user:marcos:rwx
group::r-x
group:csfadmin:r-x
mask::rwx
other::---
default:user::rwx
default:user:alissa:rwx
default:user:marcos:rwx
default:group::r-x
default:csfadmin:r-x
default:other::---
$ setfacl -m u:sergei:rwx
$ setfacl -m d:u:sergei:rwx
</pre></div>
</div>
<p>For each file and directory, there is an assigned owner and group, just like the traditional UNIX
permissions, as indicated by the lines beginning with <code class="docutils literal notranslate"><span class="pre">#</span></code>. The other lines are individual
permissions that have been set for the particular file. The user and group permissions contain
three fields separated by a colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>). The middle field indicates which user or group and the
third field indicates the permissions (read, write, execute); if the user or group field is empty,
the permission applies to the owner or group of the file. Directories can also have <code class="docutils literal notranslate"><span class="pre">default</span></code>
permission lines; any time a file is created in this directory, the specified default permissions
are automatically assigned to it. When using <code class="docutils literal notranslate"><span class="pre">setfacl</span></code> to add, change, or remove a permission
entry, the terms <code class="docutils literal notranslate"><span class="pre">user</span></code>, <code class="docutils literal notranslate"><span class="pre">group</span></code>, and <code class="docutils literal notranslate"><span class="pre">default</span></code> can be abbreviated as simply <code class="docutils literal notranslate"><span class="pre">u</span></code>, <code class="docutils literal notranslate"><span class="pre">g</span></code>, or
<code class="docutils literal notranslate"><span class="pre">d</span></code>.</p>
</div>
<table class="docutils footnote" frame="void" id="f15" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="UnixFile.html#id2">[1]</a></td><td>To reiterate the notion of files as just a sequence of bytes, note that the file
descriptor here was not necessarily the value returned from <code class="docutils literal notranslate"><span class="pre">open()</span></code> as described above. For
files that do not correspond to named locations in the directory tree structure, the file
descriptor may be created by a different function (such as <code class="docutils literal notranslate"><span class="pre">pipe()</span></code> or <code class="docutils literal notranslate"><span class="pre">socket()</span></code> as described
in Chapters 3 and 4).</td></tr>
</tbody>
</table>
<div
id="ProcFileSumm"
class="embedContainer"
data-exer-name="ProcFileSumm"
data-long-name="UNIX file questions"
data-short-name="ProcFileSumm"
data-frame-src="../../../Exercises/Processes/ProcFileSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=UnixFile&amp;JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java"
data-frame-width="950"
data-frame-height="550"
data-external="false"
data-points="1.0"
data-required="True"
data-showhide="show"
data-threshold="5"
data-type="ka"
data-exer-id="">
<div class="center">
<div id="ProcFileSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="ProcessCycle.html">2.5. Process Life Cycle</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="EventsSignals.html">2.7. Events and Signals</a>&#160;&#160;»
</div>
</div>
<br />
<div class="row jmu-dark-purple-bg">
<div class="col-md-12">
<center>
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
</center>
</div>
</div>
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>