898 lines
No EOL
78 KiB
HTML
898 lines
No EOL
78 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
|
||
|
||
|
||
<html lang="en">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
||
<title>10.9. Files — 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="1. Glossary" href="Glossary.html" />
|
||
<link rel="prev" title="8. Function Pointers" href="FunctionPointers.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="Files.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="Files.html#"><b>Chapter 1</b></a>
|
||
<a class="dropdown-item" href="IntroConcSysOverview.html"> 1.1. Introduction to Concurrent Systems</a>
|
||
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
||
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
||
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
||
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
||
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
||
<a class="dropdown-item" href="StateModelImplementation.html"> 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"> 2.1. Processes and OS Basics</a>
|
||
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
||
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
||
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
||
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
||
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
||
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
||
<a class="dropdown-item" href="Extended2Processes.html"> 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"> 3.1. Concurrency with IPC</a>
|
||
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
||
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
||
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
||
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
||
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
||
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
||
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
||
<a class="dropdown-item" href="Extended3Bash.html"> 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"> 4.1. Networked Concurrency</a>
|
||
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
||
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
||
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
||
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
||
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
||
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
||
<a class="dropdown-item" href="Extended4CGI.html"> 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"> 5.1. The Internet and Connectivity</a>
|
||
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
||
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
||
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
||
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
||
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
||
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
||
<a class="dropdown-item" href="Extended5DNS.html"> 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"> 6.1. Concurrency with Multithreading</a>
|
||
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
||
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
||
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
||
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
||
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
||
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
||
<a class="dropdown-item" href="Extended6Primes.html"> 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"> 7.1. Synchronization Primitives</a>
|
||
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
||
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
||
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
||
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
||
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
||
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
||
<a class="dropdown-item" href="Extended7Events.html"> 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"> 8.1. Synchronization Patterns and Problems</a>
|
||
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
||
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
||
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
||
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
||
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
||
<a class="dropdown-item" href="Extended8ModExp.html"> 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"> 9.1. Parallel and Distributed Systems</a>
|
||
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
||
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
||
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
||
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
||
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
||
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
||
<a class="dropdown-item" href="Extended9Blockchain.html"> 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"> A.1. C Language Reintroduction</a>
|
||
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
||
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
||
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
||
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
||
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
||
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
||
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
||
<a class="dropdown-item" href="Files.html"> 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/Files.rst"
|
||
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
|
||
<div class="container center">
|
||
«  <a id="prevmod" href="FunctionPointers.html">10.8. Function Pointers</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod" href="Glossary.html">11.1. Glossary</a>  »
|
||
|
||
</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 = "Files";ODSA.SETTINGS.MODULE_LONG_NAME = "Files";ODSA.SETTINGS.MODULE_CHAPTER = "Appendix A"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:26"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="id1">
|
||
<h1>10.9. Files<a class="headerlink" href="Files.html#id1" title="Permalink to this headline">¶</a></h1>
|
||
<p>The idea of organizing and storing data as a file is one of the oldest abstractions in computing,
|
||
with references to files dating back to the earliest computers in the 1940s. From the perspective of
|
||
C and the UNIX OS tradition, a file is just a sequence of bytes. Chapter 2 explores the implications
|
||
of this definition in further detail, such as the fact that not all files exist on persistent
|
||
storage devices and not all files have names. In this Appendix, for simplicity, we will adopt the
|
||
conventional interpretation of a file stored on a device, such as a hard drive or a USB-attached device.</p>
|
||
<div class="section" id="file-permissions-and-ownership">
|
||
<h2>10.9.1. File Permissions and Ownership<a class="headerlink" href="Files.html#file-permissions-and-ownership" title="Permalink to this headline">¶</a></h2>
|
||
<p>When a file is stored, there is a certain amount of information—called <a class="reference internal" href="Glossary.html#term-metadata"><span class="xref std std-term">metadata</span></a>—that is
|
||
stored alongside the file’s contents. Metadata is stored in a data structure called an
|
||
<a class="reference internal" href="Glossary.html#term-inode"><span class="xref std std-term">inode</span></a>, as discussed in Chapter 2. The inode contains a number of fields, one of which is the
|
||
files permission mode. The permission mode indicates which actions (read, write, or execute) can be
|
||
performed on a file by a particular user. These permission modes are commonly written as three octal
|
||
values to specify permissions for the user (the owner of the file), the group (a pre-defined set of
|
||
users), or others (everyone else). For each octal value, 4 (binary 100) indicates read permission, 2
|
||
(010) is write, and 1 (001) is execute. Setting one of these bits to 0 removes that permission.</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 – <sys/stat.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">chmod(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">mode_t</span> <span class="pre">mode);</span></code></dt>
|
||
<dd>Change the permissions associated with a file.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fchmod(int</span> <span class="pre">fildes,</span> <span class="pre">mode_t</span> <span class="pre">mode);</span></code></dt>
|
||
<dd>Change the permissions associated with an open file given its file descriptor.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">chmod()</span></code> and <code class="docutils literal notranslate"><span class="pre">fchmod()</span></code> functions, which can only be used by the owner of a particular
|
||
file, provide an interface to change the permissions on a file. The first argument specifies which
|
||
file, either by the standard file name (<code class="docutils literal notranslate"><span class="pre">path</span></code>) or using a file descriptor (<code class="docutils literal notranslate"><span class="pre">filedes</span></code>). The mode
|
||
argument is the new permission bit mask to apply. Although the <code class="docutils literal notranslate"><span class="pre">mode_t</span></code> type is just an integer
|
||
(e.g., 493), these numbers are written in their octal equivalent (<code class="docutils literal notranslate"><span class="pre">0755</span></code>). (The leading 0 is
|
||
required to indicate octal format.) Among the three digits, the first applies to the user, the
|
||
second to the group, and the third to others.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cla-58"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.58:</span>
|
||
<span class="cm"> Changing two files' permissions within a program</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Everyone has read access, user also has write */</span>
|
||
<span class="n">chmod</span> <span class="p">(</span><span class="s">"data.txt"</span><span class="p">,</span> <span class="mo">0644</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* User and group can execute the Python script, and the user can</span>
|
||
<span class="cm"> modify (write) it; others have no access */</span>
|
||
<span class="n">chmod</span> <span class="p">(</span><span class="s">"script.py"</span><span class="p">,</span> <span class="mo">0750</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Restrict access to a private directory */</span>
|
||
<span class="n">chmod</span> <span class="p">(</span><span class="s">"/home/csf/private_files"</span><span class="p">,</span> <span class="mo">0700</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p><a class="reference external" href="Files.html#cla-58">Code Listing A.58</a> changes the permissions on three files using the <code class="docutils literal notranslate"><span class="pre">chmod()</span></code>
|
||
function. The bit mask on line 6 (<code class="docutils literal notranslate"><span class="pre">0644</span></code>) indicates that the user will have read and write
|
||
permission (applying the bit-wise OR operator, <code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">|</span> <span class="pre">2</span> <span class="pre">=</span> <span class="pre">6</span></code>), while the group and other have only
|
||
read permission. Line 10 gives the user all permissions (<code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">|</span> <span class="pre">2</span> <span class="pre">|</span> <span class="pre">1</span> <span class="pre">=</span> <span class="pre">7</span></code>, meaning read, write, and
|
||
execute), whereas the group only has read and execute (<code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">|</span> <span class="pre">1</span> <span class="pre">=</span> <span class="pre">5</span></code>). Line 13 changes the
|
||
permission on a <em>directory</em>—a special file that “contains” other files (explained below).
|
||
Directories in the UNIX tradition are the equivalent of <em>folders</em> in the Windows family of operating
|
||
systems. The permissions here give the user full access to the directory, but the group and others
|
||
are blocked out. These operations can also be performed on the command line as follows (note that
|
||
the <code class="docutils literal notranslate"><span class="pre">chmod</span></code> utility is a C program that calls <code class="docutils literal notranslate"><span class="pre">chmod()</span></code> internally!). The <code class="docutils literal notranslate"><span class="pre">ls</span> <span class="pre">-ld</span></code> command
|
||
displays the permissions at the first part of the file, in a format <code class="docutils literal notranslate"><span class="pre">rwxrwxrwx</span></code> for the three
|
||
octal values (<code class="docutils literal notranslate"><span class="pre">-</span></code> indicates that permission is not set).</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>$ chmod 644 data.txt
|
||
$ chmod 750 script.py
|
||
$ chmod 700 /home/csf/private_files
|
||
$ ls -ld data.txt script.py /home/csf/private
|
||
-rw-r--r-- 1 csf staff 8528 Jul 31 23:20 data.txt
|
||
-rwxr-x--- 1 csf staff 440 Jul 31 23:20 script.py
|
||
drwx------ 11 csf staff 352 Jul 31 23:20 /home/csf/private
|
||
</pre></div>
|
||
</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 permission bits—particularly read and execute—are not as intuitive as their names suggest. For
|
||
instance, why is the read bit required to run the script.py Python script? As a piece of code, the
|
||
goal is to run—i.e., execute—it. Similarly, what does it mean to “execute” a directory? The
|
||
interpretation of these bits requires considering the type of file in a greater context.</p>
|
||
<p>For normal files (i.e., non-directories), the read bit indicates that a running process can open the
|
||
file and copy its contents into memory. In the case of scripting languages like Python, it is
|
||
important to understand that the process that is running is not executing the <code class="docutils literal notranslate"><span class="pre">script.py</span></code> code.
|
||
It can’t, because to “execute” code means that the CPU is performing machine-language instructions;
|
||
Python code is not machine language, because it is not compiled. Rather, the process is running the
|
||
Python interpreter (typically stored in a location like <code class="docutils literal notranslate"><span class="pre">/usr/bin/python</span></code>). The read permission
|
||
bit gives the Python interpreter access to read in <code class="docutils literal notranslate"><span class="pre">script.py</span></code> as text data. The interpreter then
|
||
simulates the execution of the program. For performance reasons, the interpreter might compile
|
||
parts of the script into machine language using <em>just-in-time compilation</em>, but that is not
|
||
necessary.</p>
|
||
<p>So if Python only needs to read the file, what is the purpose of setting the execute bit on
|
||
<code class="docutils literal notranslate"><span class="pre">script.py</span></code>? In truth—and somewhat ironically—the execute bit does not indicate that
|
||
<code class="docutils literal notranslate"><span class="pre">script.py</span></code> can be executed. The execute bit on files declares that the file should be found as
|
||
an executable within the <code class="docutils literal notranslate"><span class="pre">$PATH</span></code> environment variable—a list of locations to search for
|
||
executables—that the shell (<code class="docutils literal notranslate"><span class="pre">bash</span></code>) uses. When you type a command, <code class="docutils literal notranslate"><span class="pre">bash</span></code> searches through the
|
||
locations listed in the <code class="docutils literal notranslate"><span class="pre">$PATH</span></code> for the first match of that command name that has the execute bit
|
||
set. To start the process, <code class="docutils literal notranslate"><span class="pre">bash</span></code> looks into the file contents to look at the first line of the
|
||
program. In the case of scripts like <code class="docutils literal notranslate"><span class="pre">script.py</span></code>, the first line contains a <em>shebang</em> operator
|
||
that indicates the location of the interpreter that is needed:</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>#!/usr/bin/python
|
||
</pre></div>
|
||
</div>
|
||
<p>Consequently, executing a Python script requires the execute bit to add it to the <code class="docutils literal notranslate"><span class="pre">$PATH</span></code> that is
|
||
searched, but requires the read bit for the program to actually run.</p>
|
||
<p>The execute bit on directories is also frequently misunderstood, primarily because the bit is
|
||
misnamed for directories. A directory is not a piece of code that can be run (executed). Instead,
|
||
reading a directory is defined as listing its contents, whereas the execute bit allows the user to
|
||
<em>enter or pass through</em> the directory. For instance, consider the following file name (storing a
|
||
cryptographic key that can be used to log into a remote email service), based on the permissions above:</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>/home/csf/private/keys/email.id_rsa
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference external" href="Files.html#cla-58">Code Listing A.58</a> set <code class="docutils literal notranslate"><span class="pre">0700</span></code> permissions for the <code class="docutils literal notranslate"><span class="pre">/home/csf/private</span></code>. The read bit
|
||
allows the user to list the file contents (using the <code class="docutils literal notranslate"><span class="pre">ls</span></code> command, for instance). However,
|
||
accessing those files or the subdirectories requires the execute bit. Since the group and others
|
||
have no permissions, no one else can get access to the <code class="docutils literal notranslate"><span class="pre">keys</span></code> subdirectory, because doing so
|
||
requires passing through <code class="docutils literal notranslate"><span class="pre">private</span></code>. Since the read and execute actions are distinct, the bits can
|
||
be set independently. Setting a directory to <code class="docutils literal notranslate"><span class="pre">0444</span></code> would allow everyone to see the names of
|
||
files in the directory, but no one could access any of them or access any subdirectories. On the
|
||
other hand, setting the directory to <code class="docutils literal notranslate"><span class="pre">0111</span></code> would give everyone access to the files and
|
||
subdirectories…if they already knew the name; these permissions would not allow anyone to list
|
||
the directory contents to see the names of the files.</p>
|
||
<p>For completeness, writing to a directory means adding or removing files. When you save a new file
|
||
into a directory, you are writing to the directory by adding an entry. When you delete a file, you
|
||
are also writing by removing the entry. It is important to note that these operations are changes
|
||
to the directory, not the file itself. To be precise, this means that <strong>you do not have to own a
|
||
file in order to delete it</strong>. When you are deleting a file, you are not writing to it; you are
|
||
writing to the directory. As such, if you have data that is important and should never be deleted,
|
||
you should not place it in a directory that others can write to.</p>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">access()</span></code> function provides an interface to check a file’s permissions before trying to
|
||
access it. As with the <code class="docutils literal notranslate"><span class="pre">chmod()</span></code> function, the first parameter specifies the name of the file
|
||
being checked. The <code class="docutils literal notranslate"><span class="pre">mode</span></code> parameter is not the same as the <code class="docutils literal notranslate"><span class="pre">mode_t</span></code> type used above, because
|
||
<code class="docutils literal notranslate"><span class="pre">access()</span></code> is only checking the permissions for the current user. Furthermore, <code class="docutils literal notranslate"><span class="pre">access()</span></code> can
|
||
check more than just the standard read, write, and execute bits, so this mode does not follow the
|
||
same octal structure.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">access(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">int</span> <span class="pre">mode);</span></code></dt>
|
||
<dd>Check for permission to access the specified file.</dd>
|
||
</dl>
|
||
</div>
|
||
<p><a class="reference external" href="Files.html#cla-59">Code Listing A.59</a> uses <code class="docutils literal notranslate"><span class="pre">access()</span></code> to determine if a file is readable. Intuitively,
|
||
the <code class="docutils literal notranslate"><span class="pre">R_OK</span></code>, <code class="docutils literal notranslate"><span class="pre">W_OK</span></code>, and <code class="docutils literal notranslate"><span class="pre">X_OK</span></code> arguments (which can be successfully combined with bit-wise OR)
|
||
check for read, write, and execute permissions. The <code class="docutils literal notranslate"><span class="pre">F_OK</span></code> argument could be used to check just if
|
||
the file exists, regardless of the other access permissions. Different systems also support
|
||
additional values that could allow the user to check if a file can be deleted, if the user can
|
||
change its permissions, and so forth; these options are system-specific, though, and are not widely used.</p>
|
||
<blockquote id="cla-59">
|
||
<div><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
|
||
13
|
||
14
|
||
15
|
||
16</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.59:</span>
|
||
<span class="cm"> Checking for read permission to access a file</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Check for permission */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">access</span> <span class="p">(</span><span class="s">"data.txt"</span><span class="p">,</span> <span class="n">R_OK</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="cm">/* Access failed, so check global errno to determine why.</span>
|
||
<span class="cm"> Requires including <errno.h> */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">EACCES</span><span class="p">)</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Access denied</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="k">else</span>
|
||
<span class="nf">printf</span> <span class="p">(</span><span class="s">"Access failed for other error</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
<span class="k">else</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Access granted</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div></blockquote>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">unistd.h</span></code> header file provides additional functions that are relevant to the discussion of
|
||
access permissions. The <code class="docutils literal notranslate"><span class="pre">chown()</span></code> and <code class="docutils literal notranslate"><span class="pre">fchown()</span></code> functions provide interfaces to change which
|
||
user or group is considered the file’s owner. These functions are generally restricted in certain
|
||
ways; clearly, it would not be advisable to allow a random user to take over another’s files by
|
||
changing their ownership. Some systems allow users to run these functions only on files that they
|
||
own, whereas others restrict access to these functions to system adminstrators.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">chown(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">uid_t</span> <span class="pre">owner,</span> <span class="pre">gid_t</span> <span class="pre">group);</span></code></dt>
|
||
<dd>Change the ownership of a file path.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fchown(int</span> <span class="pre">fildes,</span> <span class="pre">uid_t</span> <span class="pre">owner,</span> <span class="pre">gid_t</span> <span class="pre">group);</span></code></dt>
|
||
<dd>Change the ownership of a file specified by a file descriptor.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">getuid()</span></code>, <code class="docutils literal notranslate"><span class="pre">geteuid()</span></code>, <code class="docutils literal notranslate"><span class="pre">getgid()</span></code>, and <code class="docutils literal notranslate"><span class="pre">getegid()</span></code> functions are not about files, per se, but they are relevant to the current discussion. These functions get information about the current process that is executing. Whenever you run a program, you create a process; the process inherits a specified user ID and group ID that control the process’s access. Consequently, when the previous examples referred to checking the “user’s” access to a file, this check is based on the user ID associated with the process executing this 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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">uid_t</span> <span class="pre">getuid(void);</span></code></dt>
|
||
<dd>Gets the real user ID of the calling process.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">uid_t</span> <span class="pre">geteuid(void);</span></code></dt>
|
||
<dd>Gets the effective user ID of the calling process.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">gid_t</span> <span class="pre">getgid(void);</span></code></dt>
|
||
<dd>Gets the real group ID of the calling process.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">gid_t</span> <span class="pre">getegid(void);</span></code></dt>
|
||
<dd>Gets the effective group ID of the calling process.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>The functions below make a distinction between the <em>real user</em> and the <em>effective user</em>.
|
||
(All of the points here also apply to the real group and effective group; we only mention the user
|
||
for brevity.) The real user is the ID of the account that initiated the creation of the process,
|
||
whereas the effective user is the one attached to the process as it runs; these IDs are typically
|
||
the same, but they do not have to be. Functions that check permissions, such as <code class="docutils literal notranslate"><span class="pre">access()</span></code>,
|
||
generally use the effective user ID, though there are exceptions where the real user ID can also
|
||
influence access decisions.</p>
|
||
<p>As an example of the distinction between the real and effective user, consider an executable file
|
||
with the <code class="docutils literal notranslate"><span class="pre">SETUID</span></code> bit set (see Chapter 2); this bit sets the process’s effective user ID to be the
|
||
user ID of the executable file’s owner, rather than the user who ran the command. One common use of
|
||
this is to have the <code class="docutils literal notranslate"><span class="pre">SETUID</span></code> bit set on a file owned by the administrative (<code class="docutils literal notranslate"><span class="pre">root</span></code>) account; the
|
||
process that runs will then have full access to the system, as it is running as root rather than a
|
||
restricted user account. This technique is how a login program can run to check a user’s password
|
||
against the full password list, but the user does not have direct access to the password file.</p>
|
||
<p>Another example of the real vs. user distinction can be manually created with the su command.
|
||
Contrary to a common belief, <code class="docutils literal notranslate"><span class="pre">su</span></code> does not necessarily mean “super user” (a common term for
|
||
<code class="docutils literal notranslate"><span class="pre">root</span></code>); rather, su means <em>substitute user</em>. Running a command with <code class="docutils literal notranslate"><span class="pre">su</span></code> will change the
|
||
effective user ID of the process, even if the <code class="docutils literal notranslate"><span class="pre">SETUID</span></code> bit is not set. For example, the following
|
||
command line would run the <code class="docutils literal notranslate"><span class="pre">ls</span></code> command based on the <code class="docutils literal notranslate"><span class="pre">csf</span></code> username <a class="footnote-reference" href="Files.html#f61" id="id3">[1]</a>, rather than the
|
||
default user typing the command. Consequently, the permission checks (to determine if the process is
|
||
allowed to list the current directory’s file contents) are based on the <code class="docutils literal notranslate"><span class="pre">csf</span></code> username, not the
|
||
actual user.</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>$ su csf ls -ltr
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="persistent-storage">
|
||
<h2>10.9.2. Persistent Storage<a class="headerlink" href="Files.html#persistent-storage" title="Permalink to this headline">¶</a></h2>
|
||
<p>Chapter 2 covers most of the details about working with files, such as reading from and writing to
|
||
them. That section, however, uses a broader definition of files than this part of the Appendix.
|
||
Here, we are focusing just on files in the traditional, common sense; i.e., those that are
|
||
persistently stored on a device such as a hard drive. The storage techniques used for these files
|
||
raise particular issues that are beneficial to understand for systems programming.</p>
|
||
<p>The first issue, which we have already discussed, is that of metadata. When a file is stored, the
|
||
metadata is stored in an inode structure. It is important to realize two facts: 1) the inode—not the
|
||
contents—actually defines the file, and 2) the inode is stored separately from the contents. In
|
||
other words, the inode—which is stored on the device—contains information to identify other blocks
|
||
of data on the device that store the file’s contents. When a file is modified, the new contents may
|
||
be written to the existing blocks, but maybe not. The new contents may be written to different
|
||
blocks, and the inode is simply changed to point to these new blocks; the old content blocks are
|
||
still present on the device, the inode just doesn’t point to them anymore. Similarly, when a file is
|
||
deleted, the content blocks are not necessarily destroyed; just the inode is deleted (in fact,
|
||
that’s not even entirely true, as we will describe in relation to directories).</p>
|
||
<p>When a file is in use (such as when you are editing a source code file in a text editor), all of the
|
||
file contents exist in memory. Generally speaking, you are not directly interfacing with the file
|
||
stored on disk; compared to accessing a copy in memory, accessing the stored copy would be
|
||
horrendously slow. As you modify the file, the version in memory and the original stored copy become
|
||
different. The unistd.h header file defines three key functions for fixing this. The <code class="docutils literal notranslate"><span class="pre">ftruncate()</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">trunctate()</span></code> functions are used to resize <a class="footnote-reference" href="Files.html#f62" id="id4">[2]</a> the file’s in-memory representation; for
|
||
instance, if you delete a large chunk of your program’s code, the text editor may run <code class="docutils literal notranslate"><span class="pre">truncate()</span></code>
|
||
to reduce the memory allocated for it.</p>
|
||
<p>These changes are not automatically propagated to the inode stored on the device. This update
|
||
typically (the details depend on the OS and the file system in use) only occurs when the file is
|
||
closed or when the process calls <code class="docutils literal notranslate"><span class="pre">fsync()</span></code>. The <code class="docutils literal notranslate"><span class="pre">fsync()</span></code> function—which is run when you save a
|
||
file—writes the contents to the storage device and updates the stored inode accordingly.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fsync(int</span> <span class="pre">fildes);</span></code></dt>
|
||
<dd>Synchronize the in-memory file contents with persistent storage.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">ftruncate(int</span> <span class="pre">fildes,</span> <span class="pre">off_t</span> <span class="pre">length);</span></code></dt>
|
||
<dd>Truncate or extend a file size to the specified length.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">truncate(const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">off_t</span> <span class="pre">length);</span></code></dt>
|
||
<dd>Truncate or extend a file size to the specified length.</dd>
|
||
</dl>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="directories-and-links">
|
||
<h2>10.9.3. Directories and Links<a class="headerlink" href="Files.html#directories-and-links" title="Permalink to this headline">¶</a></h2>
|
||
<p>It is likely that the reader is familiar with the term <em>directory</em> as it is used in relation to
|
||
files. When working at the systems level, it helps to have a more in-depth understanding than the
|
||
basic idea of directories (or folders) as places where files are stored. Specifically, it is
|
||
important to note that <strong>files are not actually stored in directories</strong>. As noted above, a file is
|
||
defined by an inode, as persistent data structure that contains the file’s metadata and pointers to
|
||
the file’s contents. The location of the inode on the device is determined by the OS and the file
|
||
system. The <em>inode number</em> is a persistent location identifier that tells the OS where to find
|
||
the inode on the device.</p>
|
||
<p>From this perspective of inodes, one may observe that we have not mentioned the concept of file
|
||
names. The reason for this is that <strong>file names do not, in fact, identify files</strong>. When we are
|
||
working at the level of inodes, files do not have names. Names are introduced by the concept of
|
||
directories. A directory is simply a special type of file that contains a mapping between a string
|
||
(name) and the corresponding inode. <a href="Files.html#filesysblocks">Figure 10.9.7</a> illustrates this concept
|
||
for two directories and two regular files.</p>
|
||
<div class="figure mb-2 align-center" id="id6">
|
||
<span id="filesysblocks"></span><a class="reference internal image-reference" href="_images/CSF-Images.A.8.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Sample blocks containing inodes and a directory's contents" src="_images/CSF-Images.A.8.png" style="width: 90%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 10.9.7: Sample blocks containing inodes and a directory’s contents</span></p>
|
||
</div>
|
||
<p>To start, assume that we are examining the directory <code class="docutils literal notranslate"><span class="pre">/home/csf</span></code>. Since directories are files
|
||
(just a special type of file), this directory has an inode and an inode number. In <a href="Files.html#filesysblocks">Figure 10.9.7</a>, the inode number for <code class="docutils literal notranslate"><span class="pre">/home/csf</span></code> is 4526, which identifies the block <a class="footnote-reference" href="Files.html#f63" id="id5">[3]</a>
|
||
of that number. That inode indicates that the file is a directory with permissions set to
|
||
<code class="docutils literal notranslate"><span class="pre">0755</span></code>, etc. The <code class="docutils literal notranslate"><span class="pre">Content</span></code> field indicates the block number containing the directory’s contents.
|
||
By examining the contents in block 51003 (the block number and the inode number are the same), we
|
||
can see that this directory contains three files: <code class="docutils literal notranslate"><span class="pre">data.txt</span></code>, <code class="docutils literal notranslate"><span class="pre">script.py</span></code>, and <code class="docutils literal notranslate"><span class="pre">private.</span></code> The
|
||
directory indicates that the string <code class="docutils literal notranslate"><span class="pre">"data.txt"</span></code> (or the full path <code class="docutils literal notranslate"><span class="pre">/home/csf/data.txt</span></code>) refers
|
||
to inode 4873. This inode indicates that the file is a regular file and its contents begin at block
|
||
52002. (For historical reasons, blocks are 512 bytes in size; if the file exceeds 512 bytes, it will
|
||
require multiple content blocks.) Similarly, blocks 5922 and 202 contain the inodes for <code class="docutils literal notranslate"><span class="pre">script.py</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">private</span></code>, respectively; the inode for the latter indicates that <code class="docutils literal notranslate"><span class="pre">private</span></code> is a directory.</p>
|
||
<p>Readers who have become comfortable with working on the command line are likely to have heard
|
||
references to “being in” or “changing to” a directory. These phrases refer to examining or changing
|
||
the current process’s <em>current working directory</em>, the default location that the process will
|
||
look for files. Note that, when you are working on the command line, you are always running a
|
||
process: the shell (typically <code class="docutils literal notranslate"><span class="pre">bash</span></code>). The <code class="docutils literal notranslate"><span class="pre">cd</span></code> command tells the <code class="docutils literal notranslate"><span class="pre">bash</span></code> process to change its
|
||
current working directory. When you run a separate program by typing a command, bash creates a new
|
||
process, and that new process inherits bash’s current working directory; this new process could
|
||
change its current working directory with the <code class="docutils literal notranslate"><span class="pre">chdir()</span></code> and <code class="docutils literal notranslate"><span class="pre">fchdir()</span></code> functions.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">chdir(const</span> <span class="pre">char</span> <span class="pre">*path);</span></code></dt>
|
||
<dd>Change the current working directory based on the provided <code class="docutils literal notranslate"><span class="pre">path</span></code>.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fchdir(int</span> <span class="pre">fd);</span></code></dt>
|
||
<dd>Change to the directory given as the open file descriptor <code class="docutils literal notranslate"><span class="pre">fd</span></code>.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>At this point, we have established that directories do not contain files or inodes; they just map a
|
||
string to an inode number. Similarly, the <code class="docutils literal notranslate"><span class="pre">chdir()</span></code> function can change which directory the
|
||
process will look in by default. Based on this understanding, we can now distinguish between
|
||
<em>hard links</em> and <em>symbolic links</em>. A hard link is a
|
||
directory reference to an inode. In <a href="Files.html#filesysblocks">Figure 10.9.7</a>, block 51003 contains an
|
||
entry for <code class="docutils literal notranslate"><span class="pre">data.txt</span></code> that links to inode 4873. Within inode 4873, there is a field that counts the
|
||
number of such links; so 4873’s link count would be at least one. This figure did not show the
|
||
contents of the <code class="docutils literal notranslate"><span class="pre">/home/csf/private</span></code> directory, but assume that it contains an entry for a file
|
||
named copy.txt that also maps to inode 4873; i.e., there is a <code class="docutils literal notranslate"><span class="pre">/home/csf/private/copy.txt</span></code> file,
|
||
and it points to the same inode as <code class="docutils literal notranslate"><span class="pre">/home/csf/data.txt</span></code>. In other words, the full path names
|
||
<code class="docutils literal notranslate"><span class="pre">/home/csf/data.txt</span></code> and <code class="docutils literal notranslate"><span class="pre">/home/csf/private/copy.txt</span></code> are both hard links to the same inode and
|
||
the inode’s reference count must be at least two. The effect of this hard link is that these two
|
||
files are the same; changing the contents of one will change the other. Such hard links are created
|
||
with the <code class="docutils literal notranslate"><span class="pre">link()</span></code> function.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">link(const</span> <span class="pre">char</span> <span class="pre">*path1,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*path2);</span></code></dt>
|
||
<dd>Make <code class="docutils literal notranslate"><span class="pre">path2</span></code> a hard link with the same attributes as <code class="docutils literal notranslate"><span class="pre">path1</span></code>.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">symlink(const</span> <span class="pre">char</span> <span class="pre">*path1,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*path2);</span></code></dt>
|
||
<dd>Make <code class="docutils literal notranslate"><span class="pre">path2</span></code> a symbolic link to the file identified by <code class="docutils literal notranslate"><span class="pre">path1</span></code>.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">unlink(const</span> <span class="pre">char</span> <span class="pre">*path);</span></code></dt>
|
||
<dd>Remove a link to a file specified by the given <code class="docutils literal notranslate"><span class="pre">path</span></code>.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>Unlike changes to a file, the <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> function only removes a single such link by deleting the
|
||
entry from the relevant directory. That is, calling <code class="docutils literal notranslate"><span class="pre">unlink()</span></code> on <code class="docutils literal notranslate"><span class="pre">/home/csf/private/copy.txt</span></code>
|
||
would remove the entry for <code class="docutils literal notranslate"><span class="pre">copy.txt</span></code> from the <code class="docutils literal notranslate"><span class="pre">/home/csf/private</span></code> directory. The file contents
|
||
could still be accessed using the <code class="docutils literal notranslate"><span class="pre">/home/csf/data.txt</span></code> path name. As long as there is at least one
|
||
reference to the file contents, the file cannot actually be “deleted” in the casual sense. In fact,
|
||
even when the reference count for an inode drops to 0, the contents are not necessarily destroyed.
|
||
Instead, the blocks containing the inode and the file contents are marked as available for future
|
||
use. Neither is truly destroyed until they are overwritten when they are assigned to a different
|
||
file in the future.</p>
|
||
<p>In contrast to hard links, a symbolic link (also known as a <em>shortcut</em> in the Windows family of OS)
|
||
is a distinct file with its own inode. The inode’s type field would indicate that it is a symbolic
|
||
link (or symlink for short) rather than a regular file. The inode’s Content would point to a content
|
||
block just like a regular file; however, the contents would be the path name that the symbolic link
|
||
points to. To illustrate the difference, consider the following command lines, which start with an
|
||
original C source file called <code class="docutils literal notranslate"><span class="pre">hello.c</span></code>:</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>$ ln hello.c link.c
|
||
$ ln -s hello.c symlink.c
|
||
$ ls -li hello.c link.c symlink.c
|
||
12909398185 -rw-r--r-- 2 csf staff 74 Feb 23 17:09 hello.c
|
||
12909398185 -rw-r--r-- 2 csf staff 74 Feb 23 17:09 link.c
|
||
12909398210 lrwxr-xr-x 1 csf staff 7 Feb 23 17:10 symlink.c -> hello.c
|
||
</pre></div>
|
||
</div>
|
||
<p>The first <code class="docutils literal notranslate"><span class="pre">ln</span></code> command uses link() to make <code class="docutils literal notranslate"><span class="pre">link.c</span></code> a hard link to the contents of <code class="docutils literal notranslate"><span class="pre">hello.c</span></code>.
|
||
The <code class="docutils literal notranslate"><span class="pre">-s</span></code> flag on the second <code class="docutils literal notranslate"><span class="pre">ln</span></code> command calls <code class="docutils literal notranslate"><span class="pre">symlink()</span></code> instead, making <code class="docutils literal notranslate"><span class="pre">symlink.c</span></code> a
|
||
symbolic link to <code class="docutils literal notranslate"><span class="pre">hello.c</span></code>; that is, <code class="docutils literal notranslate"><span class="pre">symlink.c</span></code> is a distinct special file whose contents are
|
||
the literal string <code class="docutils literal notranslate"><span class="pre">"hello.c"</span></code> to indicate the target of the link. (Note that the symbolic link
|
||
does not actually check for—or have any knowledge of—the existence of <code class="docutils literal notranslate"><span class="pre">hello.c</span></code> itself.) The <code class="docutils literal notranslate"><span class="pre">ls</span>
|
||
<span class="pre">-li</span></code> command shows metadata about the three files. The first field on each line is the respective
|
||
inode number (produced by the <code class="docutils literal notranslate"><span class="pre">-i</span></code> flag). Since <code class="docutils literal notranslate"><span class="pre">hello.c</span></code> and <code class="docutils literal notranslate"><span class="pre">link.c</span></code> are hard links to the
|
||
same contents, their inode is the same. On the other hand, <code class="docutils literal notranslate"><span class="pre">symlink.c</span></code> is a separate file with a
|
||
distinct inode number.</p>
|
||
<p>One of the key differences between hard links and symbolic links can be observed through deletion.
|
||
Hard links are bound to the actual file contents, whereas symbolic links are bound to the name. If
|
||
the target of a symbolic link (<code class="docutils literal notranslate"><span class="pre">hello.c</span></code> in this case) is deleted (the <code class="docutils literal notranslate"><span class="pre">rm</span></code> command calls
|
||
<code class="docutils literal notranslate"><span class="pre">unlink()</span></code> on the <code class="docutils literal notranslate"><span class="pre">hello.c</span></code> file name) and recreated with the same name, accessing the symbolic
|
||
link will reflect the new contents; accessing the other hard link will get the old contents. The
|
||
original contents will only be deleted when all hard links are removed.</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>$ rm hello.c
|
||
$ cat link.c
|
||
[original contents here...omitted for brevity]
|
||
$ cat symlink.c
|
||
cat: symlink.c: No such file or directory
|
||
$ echo "goodbye" > hello.c
|
||
$ cat link.c
|
||
[original contents here...omitted for brevity]
|
||
$ cat symlink.c
|
||
goodbye
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="advisory-locks">
|
||
<h2>10.9.4. Advisory Locks<a class="headerlink" href="Files.html#advisory-locks" title="Permalink to this headline">¶</a></h2>
|
||
<p>When concurrent software is working with files, there is the danger that multiple processes or
|
||
threads might try to access or modify an existing file at the same time. This situation would allow
|
||
one process or thread to change the file’s contents in ways that can cause errors in the other
|
||
process or thread. Different OS and file systems provide a variety of mechanisms to prevent this
|
||
from happening; as these approaches can vary between systems, it can be difficult to rely on them
|
||
for cross-platform software. One mechanism that generally has cross-platform support is the use of
|
||
<em>advisory locks</em>, which provide a mechanism for cooperating processes to try
|
||
to avoid this situation. In essence, an advisory lock allows a process to check if another process
|
||
has already locked the file; if so, the new process can wait until the first process is finished. As
|
||
the name implies, though, these are advisory in nature; the new process can still proceed regardless
|
||
of the first process’s claim.</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 – <sys/file.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">flock(int</span> <span class="pre">fd,</span> <span class="pre">int</span> <span class="pre">operation);</span></code></dt>
|
||
<dd>Apply or remove an advisory lock on an open file.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">flock()</span></code> function provides one mechanism to create an advisory lock on a file. Unlike some of
|
||
the previous functions we have described, <code class="docutils literal notranslate"><span class="pre">flock()</span></code> only works with file descriptors (see Chapter
|
||
2), not path names. That is, the process must have access to the file and must have already
|
||
successfully opened it. <a class="reference external" href="Files.html#cla-60">Code Listing A.60</a> demonstrates the use of flock(). (Note that
|
||
this code relies on <code class="docutils literal notranslate"><span class="pre">fork()</span></code> and <code class="docutils literal notranslate"><span class="pre">open()</span></code>, which are explained in Chapter 2. Advisory locks are
|
||
not a critical topic for the main chapter and are provided here for reference after that chapter has
|
||
been completed.)</p>
|
||
<blockquote id="cla-60">
|
||
<div><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
|
||
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 A.60:</span>
|
||
<span class="cm"> Setting an advisory lock on a file using the flock() interface</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Create a child process and race to get the file */</span>
|
||
<span class="kt">pid_t</span> <span class="n">child</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">child</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Both parent and child will open the file */</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">"movies.csv"</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">);</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">fd</span> <span class="o">></span> <span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Only one will succeed in locking it */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">flock</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">LOCK_EX</span> <span class="o">|</span> <span class="n">LOCK_NB</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Successfully locked file</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="k">else</span>
|
||
<span class="nf">printf</span> <span class="p">(</span><span class="s">"Failed to lock</span><span class="se">\n</span><span class="s">"</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">/* Add a slight pause to observe the locking */</span>
|
||
<span class="n">sleep</span> <span class="p">(</span><span class="mi">2</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div></blockquote>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">LOCK_EX</span> <span class="pre">|</span> <span class="pre">LOCK_NB</span></code> argument specifies that this process is requesting exclusive (<code class="docutils literal notranslate"><span class="pre">LOCK_EX</span></code>)
|
||
access to the file (only one access at a time) and <code class="docutils literal notranslate"><span class="pre">flock()</span></code> should run in non-blocking mode
|
||
(<code class="docutils literal notranslate"><span class="pre">LOCK_NB</span></code>). The default behavior of <code class="docutils literal notranslate"><span class="pre">flock()</span></code> is to cause current process to wait (block) if
|
||
another process already has exclusive access. In non-blocking mode, <code class="docutils literal notranslate"><span class="pre">flock()</span></code> returns a non-zero
|
||
value to indicate that the current process failed to acquire the lock. The process can then proceed
|
||
to other work that may be necessary and try to acquire the lock at a later time. The call to
|
||
<code class="docutils literal notranslate"><span class="pre">sleep()</span></code> on line 21 is included in this example to create a slight pause in both processes. That
|
||
is, without this <code class="docutils literal notranslate"><span class="pre">sleep()</span></code>, it is possible that one process would run, acquire the lock, and exit
|
||
(releasing the lock) before the other process had a chance to try for access. Including line 21
|
||
makes such timing unlikely, increasing the likelihood that the reader can observe the effects of the
|
||
failed lock when running this code.</p>
|
||
<p>In the preceding discussion, we mentioned that advisory locks allow <em>cooperating</em> processes to
|
||
coordinate their work. To be precise, two processes are cooperating in this sense only if they
|
||
originate from the same original process. That is, the process specifically uses <code class="docutils literal notranslate"><span class="pre">fork()</span></code> to
|
||
create at least one child process. Running the same program multiple times does not create
|
||
cooperating processes; these processes would not recognize each other’s claims to locking the file.</p>
|
||
<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>Although it is generally cross-platform, <code class="docutils literal notranslate"><span class="pre">flock()</span></code> does not successfully create advisory locks on
|
||
macOS. For code that truly needs to be cross-platform, <code class="docutils literal notranslate"><span class="pre">fcntl()</span></code> is the required interface for
|
||
advisory locks. The primary disadvantage of <code class="docutils literal notranslate"><span class="pre">fcntl()</span></code> is that it is an older, generic interface
|
||
for many different operations on files. Advisory locks are just one of the possible operations.</p>
|
||
</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-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 – <fcntl.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">fcntl(int</span> <span class="pre">fildes,</span> <span class="pre">int</span> <span class="pre">cmd,</span> <span class="pre">...);</span></code></dt>
|
||
<dd>Perform an operation on a file descriptor.</dd>
|
||
</dl>
|
||
</div>
|
||
<p><a class="reference external" href="Files.html#cla-61">Code Listing A.61</a> demonstrates the <code class="docutils literal notranslate"><span class="pre">fcntl()</span></code> interface for creating an advisory lock.
|
||
On lines 19 and 26, the <code class="docutils literal notranslate"><span class="pre">F_SETLK</span></code> argument tells <code class="docutils literal notranslate"><span class="pre">fcntl()</span></code> that the process is trying to set or
|
||
release a lock; the <code class="docutils literal notranslate"><span class="pre">struct</span></code> reference passed as the third argument distinguishes between these
|
||
two actions. Specifically, setting the <code class="docutils literal notranslate"><span class="pre">struct</span></code>’s <code class="docutils literal notranslate"><span class="pre">l_type</span></code> field to <code class="docutils literal notranslate"><span class="pre">F_WRLCK</span></code> indicates the
|
||
process is requesting a lock for writing to the file; locking the file for reading would require
|
||
also setting the <code class="docutils literal notranslate"><span class="pre">F_RDLCK</span></code> bit in this field. Setting the <code class="docutils literal notranslate"><span class="pre">l_type</span></code> field to <code class="docutils literal notranslate"><span class="pre">F_UNLCK</span></code> and
|
||
calling <code class="docutils literal notranslate"><span class="pre">fcntl()</span></code> again releases the lock on the file.</p>
|
||
<blockquote id="cla-61">
|
||
<div><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
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing A.61:</span>
|
||
<span class="cm"> Setting an advisory lock on a file using the fcntl() interface</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Create a child process then race to get the file */</span>
|
||
<span class="kt">pid_t</span> <span class="n">child</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">child</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Both parent and child will open the file */</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">"movies.csv"</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">);</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">fd</span> <span class="o">></span> <span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Initialize the lock for writing */</span>
|
||
<span class="k">struct</span> <span class="n">flock</span> <span class="n">lock</span><span class="p">;</span>
|
||
<span class="n">memset</span> <span class="p">(</span><span class="o">&</span><span class="n">lock</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">lock</span><span class="p">));</span>
|
||
<span class="n">lock</span><span class="p">.</span><span class="n">l_type</span> <span class="o">=</span> <span class="n">F_WRLCK</span><span class="p">;</span>
|
||
|
||
<span class="cm">/* Only one will succeed in locking it */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">fcntl</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">F_SETLK</span><span class="p">,</span> <span class="o">&</span><span class="n">lock</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Successfully locked file</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="cm">/* Add a slight pause to observe the locking */</span>
|
||
<span class="n">sleep</span> <span class="p">(</span><span class="mi">2</span><span class="p">);</span>
|
||
<span class="cm">/* Now release the lock */</span>
|
||
<span class="n">lock</span><span class="p">.</span><span class="n">l_type</span> <span class="o">=</span> <span class="n">F_UNLCK</span><span class="p">;</span>
|
||
<span class="n">fcntl</span> <span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">F_SETLK</span><span class="p">,</span> <span class="o">&</span><span class="n">lock</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
<span class="k">else</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Failed to lock</span><span class="se">\n</span><span class="s">"</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>
|
||
</div></blockquote>
|
||
<table class="docutils footnote" frame="void" id="f61" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="Files.html#id3">[1]</a></td><td>In the UNIX tradition, <em>username</em> refers to the human-readable identifier that user can
|
||
remember and use easily. Internally, all usernames are mapped to a user ID, which is just an integer value.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="f62" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="Files.html#id4">[2]</a></td><td>These functions are poorly named. The standard definition of the word “truncate” means to
|
||
reduce the size of something. However, the C <code class="docutils literal notranslate"><span class="pre">truncate()</span></code> function can also be used to increase the file’s size.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="f63" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="Files.html#id5">[3]</a></td><td>Typical storage devices organize the device into what is essentially a gigantic array of
|
||
fixed-size blocks. While the details are more complicated than this, it is sufficient for our
|
||
purposes to think of accessing a block just as we would index an array.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<div class="mt-4 container center">
|
||
«  <a id="prevmod1" href="FunctionPointers.html">10.8. Function Pointers</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod1" href="Glossary.html">11.1. Glossary</a>  »
|
||
</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> |