inweb-bootstrap/docs/foundation-module/3-cf.html

392 lines
43 KiB
HTML
Raw Normal View History

2019-02-04 22:26:45 +00:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
2020-04-08 22:41:00 +00:00
<title>Case-Insensitive Filenames</title>
<meta name="viewport" content="width=device-width initial-scale=1">
2019-02-04 22:26:45 +00:00
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
2020-04-10 20:29:28 +00:00
2019-02-04 22:26:45 +00:00
</head>
<body>
<nav role="navigation">
2020-04-13 16:06:45 +00:00
<h1><a href="../index.html">
<img src="../..//docs/docs-src/Figures/Octagram184x184.png" width=72 height=72">
</a></h1>
<ul><li><a href="../inweb/index.html">inweb</a></li>
</ul><h2>Foundation Module</h2><ul>
<li><a href="index.html"><span class="selectedlink">foundation</span></a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
2020-04-13 16:06:45 +00:00
</ul><h2>Example Webs</h2><ul>
2020-04-12 16:24:23 +00:00
<li><a href="../goldbach/index.html">goldbach</a></li>
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
2020-04-13 16:06:45 +00:00
</ul><h2>External</h2><ul>
<li><a href="https://github.com/ganelson/inweb">github</a></li>
2020-04-13 16:06:45 +00:00
</ul>
</nav>
<main role="main">
2020-04-08 22:41:00 +00:00
<!--Weave of 'Case-Insensitive Filenames' generated by 7-->
2020-04-13 16:06:45 +00:00
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#3">Chapter 3: The Operating System</a></li><li><b>Case-Insensitive Filenames</b></li></ul><p class="purpose">On some of the Unix-derived file systems on which Inform runs, filenames are case-sensitive, so that FISH and fish might be different files. This makes extension files, installed by the user, prone to being missed. The code in this section provides a routine to carry out file opening as if filenames are case-insensitive, and is used only for extensions.</p>
2019-02-04 22:26:45 +00:00
<ul class="toc"><li><a href="#SP3">&#167;3. The routine</a></li><li><a href="#SP3_1">&#167;3.1. Looking for case-insensitive matches instead</a></li><li><a href="#SP3_3">&#167;3.3. Allocation and deallocation</a></li><li><a href="#SP3_6">&#167;3.6. Pathname hacking</a></li><li><a href="#SP4">&#167;4. Counting matches</a></li><li><a href="#SP5">&#167;5. Non-POSIX tail</a></li></ul><hr class="tocbar">
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>This section contains a single utility routine, contributed by Adam
Thornton: a specialised, case-insensitive form of <code class="display"><span class="extract">fopen()</span></code>. It is specialised
in that it is designed for opening extensions, where the file path will be
case-correct up to the last two components of the path (the leafname and the
immediately containing directory), but where the casing may be wrong in those
last two components.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>If the exact filename or extension directory (case-correct) exists,
<code class="display"><span class="extract">CIFilingSystem::fopen()</span></code> will choose it to open. If not, it will
use <code class="display"><span class="extract">strcasecmp()</span></code> to find a file or directory with the same name but
differing in case and use it instead. If it finds exactly one candidate file,
it will then attempt to <code class="display"><span class="extract">fopen()</span></code> it and return the result.
</p>
<p class="inwebparagraph">If <code class="display"><span class="extract">CIFilingSystem::fopen()</span></code> succeeds, it returns a <code class="display"><span class="extract">FILE *</span></code>
(passed back to it from the underlying <code class="display"><span class="extract">fopen()</span></code>). If
<code class="display"><span class="extract">CIFilingSystem::fopen()</span></code> fails, it returns <code class="display"><span class="extract">NULL</span></code>, and
<code class="display"><span class="extract">errno</span></code> is set accordingly:
</p>
<ul class="items"><li>(a) If no suitable file was found, <code class="display"><span class="extract">errno</span></code> is set to <code class="display"><span class="extract">ENOENT</span></code>.
</li><li>(b) If more than one possibility was found, but none of them exactly match
the supplied case, <code class="display"><span class="extract">errno</span></code> is set to <code class="display"><span class="extract">EBADF</span></code>.
</li><li>(c) Note that if multiple directories which match case-insensitively are
found, but none is an exact match, <code class="display"><span class="extract">EBADF</span></code> will be set regardless of the
contents of the directories.
</li><li>(d) If <code class="display"><span class="extract">CIFilingSystem::fopen()</span></code> fails during its allocation of
space to hold its intermediate strings for comparison, or for its various
data structures, <code class="display"><span class="extract">errno</span></code> is set to <code class="display"><span class="extract">ENOMEM</span></code>.
</li><li>(e) If an unambiguous filename is found but the <code class="display"><span class="extract">fopen()</span></code> fails, <code class="display"><span class="extract">errno</span></code> is
left at whatever value the underlying <code class="display"><span class="extract">fopen()</span></code> set it to.
</li></ul>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. The routine. </b>The routine is available only on POSIX platforms where <code class="display"><span class="extract">PLATFORM_POSIX</span></code>
2019-02-04 22:26:45 +00:00
is defined (see "Platform-Specific Definitions"). In practice this means
everywhere except Windows, but all Windows file systems are case-preserving
and case-insensitive in any case.
</p>
<p class="inwebparagraph">Briefly, we try to get the extension directory name right first, by looking
2019-02-04 22:26:45 +00:00
for the given casing, then if that fails, for a unique alternative with
different casing; and then repeat within that directory for the extension
file itself.
</p>
<pre class="display">
<span class="reserved">FILE</span><span class="plain"> *</span><span class="functiontext"><a href="#SP5">CIFilingSystem::fopen</a></span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">path</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">mode</span><span class="plain">) {</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">topdirpath</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">ciextdirpath</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">cistring</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">ciextname</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">workstring</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">workstring2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">DIR</span><span class="plain"> *</span><span class="identifier">topdir</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">extdir</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">handle</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">size_t</span><span class="plain"> </span><span class="identifier">length</span><span class="plain">;</span>
<span class="comment"> for efficiency's sake, though it's logically equivalent, we try...</span>
2020-04-06 11:26:10 +00:00
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">fopen</span><span class="plain">(</span><span class="identifier">path</span><span class="plain">, </span><span class="identifier">mode</span><span class="plain">); </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">handle</span><span class="plain">) </span>&lt;<span class="cwebmacro">Happy ending to ci-fopen</span> <span class="cwebmacronumber">3.4</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
&lt;<span class="cwebmacro">Find the length of the path, giving an error if it is empty or NULL</span> <span class="cwebmacronumber">3.6</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Allocate memory for strings large enough to hold any subpath of the path</span> <span class="cwebmacronumber">3.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Parse the path to break it into topdir path, extension directory and leafname</span> <span class="cwebmacronumber">3.7</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">topdir</span><span class="plain"> = </span><span class="identifier">opendir</span><span class="plain">(</span><span class="identifier">topdirpath</span><span class="plain">); </span><span class="comment"> whose pathname is assumed case-correct...</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">topdir</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; </span> <span class="comment"> ...so that failure is fatal; <code class="display"><span class="extract">errno</span></code> is set by <code class="display"><span class="extract">opendir</span></code></span>
2019-02-04 22:26:45 +00:00
2020-04-06 11:26:10 +00:00
<span class="identifier">sprintf</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">, </span><span class="string">"%s%c%s"</span><span class="plain">, </span><span class="identifier">topdirpath</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">, </span><span class="identifier">ciextdirpath</span><span class="plain">);</span>
<span class="identifier">extdir</span><span class="plain"> = </span><span class="identifier">opendir</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">); </span><span class="comment"> try with supplied extension directory name</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">extdir</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Try to find a unique insensitively matching directory name in topdir</span> <span class="cwebmacronumber">3.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">strcpy</span><span class="plain">(</span><span class="identifier">cistring</span><span class="plain">, </span><span class="identifier">workstring</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
2020-04-06 11:26:10 +00:00
<span class="identifier">sprintf</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">, </span><span class="string">"%s%c%s"</span><span class="plain">, </span><span class="identifier">cistring</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">, </span><span class="identifier">ciextname</span><span class="plain">);</span>
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">fopen</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">, </span><span class="identifier">mode</span><span class="plain">); </span><span class="comment"> try with supplied name</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">handle</span><span class="plain">) </span>&lt;<span class="cwebmacro">Happy ending to ci-fopen</span> <span class="cwebmacronumber">3.4</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
&lt;<span class="cwebmacro">Try to find a unique insensitively matching entry in extdir</span> <span class="cwebmacronumber">3.2</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This paragraph is used only if PLATFORM_POSIX is defined.</p>
2020-04-11 20:39:43 +00:00
<p class="endnote">The function CIFilingSystem::fopen is used in <a href="#SP5">&#167;5</a>, Filenames (<a href="3-fln.html#SP10">&#167;10</a>).</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. Looking for case-insensitive matches instead. </b>We emerge from the following only in the happy case where a unique matching
2019-02-04 22:26:45 +00:00
directory name can be found.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Try to find a unique insensitively matching directory name in topdir</span> <span class="cwebmacronumber">3.1</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rc</span><span class="plain"> = </span><span class="functiontext"><a href="#SP4">CIFilingSystem::match_in_directory</a></span><span class="plain">(</span><span class="identifier">topdir</span><span class="plain">, </span><span class="identifier">ciextdirpath</span><span class="plain">, </span><span class="identifier">workstring</span><span class="plain">);</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">rc</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">0</span><span class="plain">:</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOENT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">case</span><span class="plain"> </span><span class="constant">1</span><span class="plain">:</span>
<span class="identifier">sprintf</span><span class="plain">(</span><span class="identifier">cistring</span><span class="plain">, </span><span class="string">"%s%c%s"</span><span class="plain">, </span><span class="identifier">topdirpath</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">, </span><span class="identifier">workstring</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">extdir</span><span class="plain"> = </span><span class="identifier">opendir</span><span class="plain">(</span><span class="identifier">cistring</span><span class="plain">);</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">extdir</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOENT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">break</span><span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">default:</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">EBADF</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_2"></a><b>&#167;3.2. </b>More or less the same, but we never emerge at all: all cases of the switch
2019-02-04 22:26:45 +00:00
return from the function.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Try to find a unique insensitively matching entry in extdir</span> <span class="cwebmacronumber">3.2</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rc</span><span class="plain"> = </span><span class="functiontext"><a href="#SP4">CIFilingSystem::match_in_directory</a></span><span class="plain">(</span><span class="identifier">extdir</span><span class="plain">, </span><span class="identifier">ciextname</span><span class="plain">, </span><span class="identifier">workstring</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
2020-04-06 11:26:10 +00:00
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">rc</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">0</span><span class="plain">:</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOENT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">case</span><span class="plain"> </span><span class="constant">1</span><span class="plain">:</span>
<span class="identifier">sprintf</span><span class="plain">(</span><span class="identifier">workstring2</span><span class="plain">, </span><span class="string">"%s%c%s"</span><span class="plain">, </span><span class="identifier">cistring</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">, </span><span class="identifier">workstring</span><span class="plain">);</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">workstring2</span><span class="plain">[</span><span class="identifier">length</span><span class="plain">] = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">fopen</span><span class="plain">(</span><span class="identifier">workstring2</span><span class="plain">, </span><span class="identifier">mode</span><span class="plain">);</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">handle</span><span class="plain">) </span>&lt;<span class="cwebmacro">Happy ending to ci-fopen</span> <span class="cwebmacronumber">3.4</span>&gt;<span class="plain">;</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOENT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">default:</span>
<span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">EBADF</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_3"></a><b>&#167;3.3. Allocation and deallocation. </b>We use six strings to hold full or partial pathnames.
2019-02-04 22:26:45 +00:00
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Allocate memory for strings large enough to hold any subpath of the path</span> <span class="cwebmacronumber">3.3</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-06 11:26:10 +00:00
<span class="identifier">workstring</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">workstring</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
<span class="identifier">workstring2</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">workstring2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
<span class="identifier">topdirpath</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">topdirpath</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
<span class="identifier">ciextdirpath</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ciextdirpath</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
<span class="identifier">cistring</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cistring</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
<span class="identifier">ciextname</span><span class="plain"> = </span><span class="identifier">calloc</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">+1, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">char</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ciextname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOMEM</span><span class="plain">; </span>&lt;<span class="cwebmacro">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt;<span class="plain">; }</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_4"></a><b>&#167;3.4. </b>If we are successful, we return a valid file handle...
2019-02-04 22:26:45 +00:00
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Happy ending to ci-fopen</span> <span class="cwebmacronumber">3.4</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Prepare to exit ci-fopen cleanly</span> <span class="cwebmacronumber">3.4.1</span>&gt;<span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">handle</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a> (twice), <a href="#SP3_2">&#167;3.2</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_5"></a><b>&#167;3.5. </b>...and otherwise <code class="display"><span class="extract">NULL</span></code>, having already set <code class="display"><span class="extract">errno</span></code> with the reason why.
2019-02-04 22:26:45 +00:00
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Sad ending to ci-fopen</span> <span class="cwebmacronumber">3.5</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Prepare to exit ci-fopen cleanly</span> <span class="cwebmacronumber">3.4.1</span>&gt;<span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>, <a href="#SP3_1">&#167;3.1</a> (three times), <a href="#SP3_2">&#167;3.2</a> (three times), <a href="#SP3_3">&#167;3.3</a> (6 times).</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_4_1"></a><b>&#167;3.4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Prepare to exit ci-fopen cleanly</span> <span class="cwebmacronumber">3.4.1</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">workstring</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">workstring2</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">workstring2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">topdirpath</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">topdirpath</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ciextdirpath</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">ciextdirpath</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cistring</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">cistring</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ciextname</span><span class="plain">) </span><span class="identifier">free</span><span class="plain">(</span><span class="identifier">ciextname</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">topdir</span><span class="plain">) </span><span class="identifier">closedir</span><span class="plain">(</span><span class="identifier">topdir</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">extdir</span><span class="plain">) </span><span class="identifier">closedir</span><span class="plain">(</span><span class="identifier">extdir</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3_4">&#167;3.4</a>, <a href="#SP3_5">&#167;3.5</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_6"></a><b>&#167;3.6. Pathname hacking. </b></p>
2019-02-04 22:26:45 +00:00
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Find the length of the path, giving an error if it is empty or NULL</span> <span class="cwebmacronumber">3.6</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-04 19:46:43 +00:00
<span class="identifier">length</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">path</span><span class="plain">) </span><span class="identifier">length</span><span class="plain"> = (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">strlen</span><span class="plain">(</span><span class="identifier">path</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">length</span><span class="plain"> &lt; </span><span class="constant">1</span><span class="plain">) { </span><span class="identifier">errno</span><span class="plain"> = </span><span class="identifier">ENOENT</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">; }</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP3_7"></a><b>&#167;3.7. </b>And here we break up a pathname like
2019-02-04 22:26:45 +00:00
</p>
<pre class="display">
<span class="plain">/Users/bobama/Library/Inform/Extensions/Hillary Clinton/Health Care.i7x</span>
</pre>
<p class="inwebparagraph">into three components:
</p>
2020-04-07 22:04:32 +00:00
<ul class="items"><li>(a) <code class="display"><span class="extract">topdirpath</span></code> is <code class="display"><span class="extract">/Users/bobama/Library/Inform/Extensions</span></code>, and its casing is correct.
</li><li>(b) <code class="display"><span class="extract">ciextdirpath</span></code> is <code class="display"><span class="extract">Hillary Clinton</span></code>, but its casing may not be correct.
</li><li>(c) <code class="display"><span class="extract">ciextname</span></code> is <code class="display"><span class="extract">Health Care.i7x</span></code>, but its casing may not be correct.
</li></ul>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph">The contents of <code class="display"><span class="extract">workstring</span></code> are not significant afterwards.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse the path to break it into topdir path, extension directory and leafname</span> <span class="cwebmacronumber">3.7</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-06 11:26:10 +00:00
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">size_t</span><span class="plain"> </span><span class="identifier">extdirindex</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">extindex</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">namelen</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">dirlen</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
2020-04-06 11:26:10 +00:00
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">strrchr</span><span class="plain">(</span><span class="identifier">path</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">extindex</span><span class="plain"> = (</span><span class="identifier">size_t</span><span class="plain">) (</span><span class="identifier">p</span><span class="plain"> - </span><span class="identifier">path</span><span class="plain">);</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">namelen</span><span class="plain"> = </span><span class="identifier">length</span><span class="plain"> - </span><span class="identifier">extindex</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">strncpy</span><span class="plain">(</span><span class="identifier">ciextname</span><span class="plain">, </span><span class="identifier">path</span><span class="plain"> + </span><span class="identifier">extindex</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">namelen</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">ciextname</span><span class="plain">[</span><span class="identifier">namelen</span><span class="plain">] = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">strncpy</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">, </span><span class="identifier">path</span><span class="plain">, </span><span class="identifier">extindex</span><span class="plain">);</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">workstring</span><span class="plain">[</span><span class="identifier">extindex</span><span class="plain">] = </span><span class="constant">0</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">strrchr</span><span class="plain">(</span><span class="identifier">workstring</span><span class="plain">, </span><span class="constant">FOLDER_SEPARATOR</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">extdirindex</span><span class="plain"> = (</span><span class="identifier">size_t</span><span class="plain">) (</span><span class="identifier">p</span><span class="plain"> - </span><span class="identifier">workstring</span><span class="plain">);</span>
<span class="identifier">strncpy</span><span class="plain">(</span><span class="identifier">topdirpath</span><span class="plain">, </span><span class="identifier">path</span><span class="plain">, </span><span class="identifier">extdirindex</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">topdirpath</span><span class="plain">[</span><span class="identifier">extdirindex</span><span class="plain">] = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">dirlen</span><span class="plain"> = </span><span class="identifier">extindex</span><span class="plain"> - </span><span class="identifier">extdirindex</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dirlen</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">dirlen</span><span class="plain"> -= </span><span class="constant">1</span><span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">strncpy</span><span class="plain">(</span><span class="identifier">ciextdirpath</span><span class="plain">, </span><span class="identifier">path</span><span class="plain"> + </span><span class="identifier">extdirindex</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">dirlen</span><span class="plain">);</span>
<span class="identifier">ciextdirpath</span><span class="plain">[</span><span class="identifier">dirlen</span><span class="plain">] = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Counting matches. </b>We count the number of names within the directory which case-insensitively
2019-02-04 22:26:45 +00:00
match against <code class="display"><span class="extract">name</span></code>, and copy the last which matches into <code class="display"><span class="extract">last_match</span></code>.
This must be at least as long as <code class="display"><span class="extract">name</span></code>. (We ought to be just a little careful
in case of improbable cases where the matched name contains a different
number of characters from <code class="display"><span class="extract">name</span></code>, for instance because on a strict reading
of Unicode "SS" is casing-equivalent to the eszet, but it's unlikely
that many contemporary implementations of <code class="display"><span class="extract">strcasecmp</span></code> are aware of this,
and in any case the code above contains much larger buffers than needed.)
</p>
<pre class="display">
2020-04-12 23:41:59 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CIFilingSystem::match_in_directory<button class="popup" onclick="togglePopup('usagePopup221')">...<span class="popuptext" id="usagePopup221">Usage of <b>CIFilingSystem::match_in_directory</b>:<br><a href="#SP3_1">&#167;3.1</a>, <a href="#SP3_2">&#167;3.2</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vd</span><span class="plain">,</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">last_match</span><span class="plain">) {</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">DIR</span><span class="plain"> *</span><span class="identifier">d</span><span class="plain"> = (</span><span class="identifier">DIR</span><span class="plain"> *) </span><span class="identifier">vd</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">dirent</span><span class="plain"> *</span><span class="identifier">dirp</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rc</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
2020-04-04 19:46:43 +00:00
<span class="identifier">last_match</span><span class="plain">[0] = </span><span class="constant">0</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">dirp</span><span class="plain"> = </span><span class="identifier">readdir</span><span class="plain">(</span><span class="identifier">d</span><span class="plain">)) != </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">strcasecmp</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">dirp</span><span class="plain">-&gt;</span><span class="identifier">d_name</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) {</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">rc</span><span class="plain">++;</span>
<span class="identifier">strcpy</span><span class="plain">(</span><span class="identifier">last_match</span><span class="plain">, </span><span class="identifier">dirp</span><span class="plain">-&gt;</span><span class="identifier">d_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rc</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Non-POSIX tail. </b>On platforms without POSIX directory handling, we revert to regular <code class="display"><span class="extract">fopen</span></code>.
2019-02-04 22:26:45 +00:00
</p>
<pre class="display">
2020-04-12 23:41:59 +00:00
<span class="reserved">FILE</span><span class="plain"> *</span><span class="functiontext">CIFilingSystem::fopen<button class="popup" onclick="togglePopup('usagePopup222')">...<span class="popuptext" id="usagePopup222">Usage of <b>CIFilingSystem::fopen</b>:<br><a href="#SP3">&#167;3</a>, Filenames - <a href="3-fln.html#SP10">&#167;10</a></span></button></span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">path</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">mode</span><span class="plain">) {</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">fopen</span><span class="plain">(</span><span class="identifier">path</span><span class="plain">, </span><span class="identifier">mode</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This paragraph is used only if PLATFORM_POSIX is undefined.</p>
2019-03-12 23:32:12 +00:00
<hr class="tocbar">
<ul class="toc"><li><a href="3-fln.html">Back to 'Filenames'</a></li><li><a href="3-shl.html">Continue with 'Shell'</a></li></ul><hr class="tocbar">
<!--End of weave-->
2020-04-11 20:39:43 +00:00
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
</main>
2019-02-04 22:26:45 +00:00
</body>
</html>