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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>libfuse: example/passthrough_ll.c File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">libfuse
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',false,false,'search.php','Search');
});
</script>
<div id="main-nav"></div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="dir_cfafba98a580ce4b62f8a6fa96d7cbb0.html">example</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">passthrough_ll.c File Reference</div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><code>#include "config.h"</code><br />
<code>#include <<a class="el" href="fuse__lowlevel_8h_source.html">fuse_lowlevel.h</a>></code><br />
<code>#include <unistd.h></code><br />
<code>#include <stdlib.h></code><br />
<code>#include <stdio.h></code><br />
<code>#include <stddef.h></code><br />
<code>#include <stdbool.h></code><br />
<code>#include <string.h></code><br />
<code>#include <limits.h></code><br />
<code>#include <dirent.h></code><br />
<code>#include <assert.h></code><br />
<code>#include <errno.h></code><br />
<code>#include <err.h></code><br />
<code>#include <inttypes.h></code><br />
<code>#include <pthread.h></code><br />
<code>#include <sys/file.h></code><br />
<code>#include <sys/xattr.h></code><br />
</div>
<p><a href="passthrough__ll_8c_source.html">Go to the source code of this file.</a></p>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p>This file system mirrors the existing file system hierarchy of the system, starting at the root file system. This is implemented by just "passing through" all requests to the corresponding user-space libc functions. In contrast to <a class="el" href="passthrough_8c.html">passthrough.c</a> and <a class="el" href="passthrough__fh_8c.html">passthrough_fh.c</a>, this implementation uses the low-level API. Its performance should be the least bad among the three, but many operations are not implemented. In particular, it is not possible to remove files (or directories) because the code necessary to defer actual removal until the file is not opened anymore would make the example much more complicated.</p>
<p>When writeback caching is enabled (-o writeback mount option), it is only possible to write to files for which the mounting user has read permissions. This is because the writeback cache requires the kernel to be able to issue read requests for all files (which the passthrough filesystem cannot satisfy if it can't read the file in the underlying filesystem).</p>
<p>Compile with: </p><pre class="fragment">gcc -Wall passthrough_ll.c `pkg-config fuse3 --cflags --libs` -o passthrough_ll
</pre><h2>Source code</h2>
<div class="fragment"><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> FUSE: Filesystem in Userspace</span></div><div class="line"><span class="comment"> Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu></span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment"> This program can be distributed under the terms of the GNU GPL.</span></div><div class="line"><span class="comment"> See the file COPYING.</span></div><div class="line"><span class="comment">*/</span></div><div class="line"></div><div class="line"><span class="preprocessor">#define _GNU_SOURCE</span></div><div class="line"><span class="preprocessor">#define FUSE_USE_VERSION 31</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include "config.h"</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include <<a class="code" href="fuse__lowlevel_8h.html">fuse_lowlevel.h</a>></span></div><div class="line"><span class="preprocessor">#include <unistd.h></span></div><div class="line"><span class="preprocessor">#include <stdlib.h></span></div><div class="line"><span class="preprocessor">#include <stdio.h></span></div><div class="line"><span class="preprocessor">#include <stddef.h></span></div><div class="line"><span class="preprocessor">#include <stdbool.h></span></div><div class="line"><span class="preprocessor">#include <string.h></span></div><div class="line"><span class="preprocessor">#include <limits.h></span></div><div class="line"><span class="preprocessor">#include <dirent.h></span></div><div class="line"><span class="preprocessor">#include <assert.h></span></div><div class="line"><span class="preprocessor">#include <errno.h></span></div><div class="line"><span class="preprocessor">#include <err.h></span></div><div class="line"><span class="preprocessor">#include <inttypes.h></span></div><div class="line"><span class="preprocessor">#include <pthread.h></span></div><div class="line"><span class="preprocessor">#include <sys/file.h></span></div><div class="line"><span class="preprocessor">#include <sys/xattr.h></span></div><div class="line"></div><div class="line"><span class="comment">/* We are re-using pointers to our `struct lo_inode` and `struct</span></div><div class="line"><span class="comment"> lo_dirp` elements as inodes. This means that we must be able to</span></div><div class="line"><span class="comment"> store uintptr_t values in a fuse_ino_t variable. The following</span></div><div class="line"><span class="comment"> incantation checks this condition at compile time. */</span></div><div class="line"><span class="preprocessor">#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus</span></div><div class="line">_Static_assert(<span class="keyword">sizeof</span>(<a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a>) >= <span class="keyword">sizeof</span>(uintptr_t),</div><div class="line"> <span class="stringliteral">"fuse_ino_t too small to hold uintptr_t values!"</span>);</div><div class="line"><span class="preprocessor">#else</span></div><div class="line"><span class="keyword">struct </span>_uintptr_to_must_hold_fuse_ino_t_dummy_struct \</div><div class="line"> { <span class="keywordtype">unsigned</span> _uintptr_to_must_hold_fuse_ino_t:</div><div class="line"> ((<span class="keyword">sizeof</span>(<a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a>) >= <span class="keyword">sizeof</span>(uintptr_t)) ? 1 : -1); };</div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="keyword">struct </span>lo_inode {</div><div class="line"> <span class="keyword">struct </span>lo_inode *next; <span class="comment">/* protected by lo->mutex */</span></div><div class="line"> <span class="keyword">struct </span>lo_inode *prev; <span class="comment">/* protected by lo->mutex */</span></div><div class="line"> <span class="keywordtype">int</span> fd;</div><div class="line"> <span class="keywordtype">bool</span> is_symlink;</div><div class="line"> ino_t ino;</div><div class="line"> dev_t dev;</div><div class="line"> uint64_t refcount; <span class="comment">/* protected by lo->mutex */</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">enum</span> {</div><div class="line"> CACHE_NEVER,</div><div class="line"> CACHE_NORMAL,</div><div class="line"> CACHE_ALWAYS,</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">struct </span>lo_data {</div><div class="line"> pthread_mutex_t mutex;</div><div class="line"> <span class="keywordtype">int</span> debug;</div><div class="line"> <span class="keywordtype">int</span> writeback;</div><div class="line"> <span class="keywordtype">int</span> flock;</div><div class="line"> <span class="keywordtype">int</span> xattr;</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *source;</div><div class="line"> <span class="keywordtype">double</span> timeout;</div><div class="line"> <span class="keywordtype">int</span> cache;</div><div class="line"> <span class="keywordtype">int</span> timeout_set;</div><div class="line"> <span class="keyword">struct </span>lo_inode root; <span class="comment">/* protected by lo->mutex */</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">struct </span><a class="code" href="structfuse__opt.html">fuse_opt</a> lo_opts[] = {</div><div class="line"> { <span class="stringliteral">"writeback"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, writeback), 1 },</div><div class="line"> { <span class="stringliteral">"no_writeback"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, writeback), 0 },</div><div class="line"> { <span class="stringliteral">"source=%s"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, source), 0 },</div><div class="line"> { <span class="stringliteral">"flock"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, flock), 1 },</div><div class="line"> { <span class="stringliteral">"no_flock"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, flock), 0 },</div><div class="line"> { <span class="stringliteral">"xattr"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, xattr), 1 },</div><div class="line"> { <span class="stringliteral">"no_xattr"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, xattr), 0 },</div><div class="line"> { <span class="stringliteral">"timeout=%lf"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, timeout), 0 },</div><div class="line"> { <span class="stringliteral">"timeout="</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, timeout_set), 1 },</div><div class="line"> { <span class="stringliteral">"cache=never"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, cache), CACHE_NEVER },</div><div class="line"> { <span class="stringliteral">"cache=auto"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, cache), CACHE_NORMAL },</div><div class="line"> { <span class="stringliteral">"cache=always"</span>,</div><div class="line"> offsetof(<span class="keyword">struct</span> lo_data, cache), CACHE_ALWAYS },</div><div class="line"></div><div class="line"> <a class="code" href="fuse__opt_8h.html#aca35962e17d189ceb5447f8eea11bd33">FUSE_OPT_END</a></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>lo_data *lo_data(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> (<span class="keyword">struct</span> lo_data *) <a class="code" href="fuse__lowlevel_8h.html#aab00273c65d124e44abcf2374f9c504b">fuse_req_userdata</a>(req);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>lo_inode *lo_inode(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino)</div><div class="line">{</div><div class="line"> <span class="keywordflow">if</span> (ino == <a class="code" href="fuse__lowlevel_8h.html#a14d7299559cf05272b838cfc6388ef91">FUSE_ROOT_ID</a>)</div><div class="line"> <span class="keywordflow">return</span> &lo_data(req)->root;</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <span class="keywordflow">return</span> (<span class="keyword">struct</span> lo_inode *) (uintptr_t) ino;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> lo_fd(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> lo_inode(req, ino)->fd;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">bool</span> lo_debug(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> lo_data(req)->debug != 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_init(<span class="keywordtype">void</span> *userdata,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__conn__info.html">fuse_conn_info</a> *conn)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = (<span class="keyword">struct </span>lo_data*) userdata;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span>(conn-><a class="code" href="structfuse__conn__info.html#a8a1c61f5d7cc14249fb6971165bb958e">capable</a> & <a class="code" href="fuse__common_8h.html#a7686c11aaf80382189927b10b848d8c8">FUSE_CAP_EXPORT_SUPPORT</a>)</div><div class="line"> conn-><a class="code" href="structfuse__conn__info.html#af45de81548b591f3004353a324e4e04d">want</a> |= <a class="code" href="fuse__common_8h.html#a7686c11aaf80382189927b10b848d8c8">FUSE_CAP_EXPORT_SUPPORT</a>;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo->writeback &&</div><div class="line"> conn-><a class="code" href="structfuse__conn__info.html#a8a1c61f5d7cc14249fb6971165bb958e">capable</a> & <a class="code" href="fuse__common_8h.html#a4839fce31097f4b4da7a1f01169228fa">FUSE_CAP_WRITEBACK_CACHE</a>) {</div><div class="line"> <span class="keywordflow">if</span> (lo->debug)</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_init: activating writeback\n"</span>);</div><div class="line"> conn-><a class="code" href="structfuse__conn__info.html#af45de81548b591f3004353a324e4e04d">want</a> |= <a class="code" href="fuse__common_8h.html#a4839fce31097f4b4da7a1f01169228fa">FUSE_CAP_WRITEBACK_CACHE</a>;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (lo->flock && conn-><a class="code" href="structfuse__conn__info.html#a8a1c61f5d7cc14249fb6971165bb958e">capable</a> & <a class="code" href="fuse__common_8h.html#afd06393448dbb60668f5a3bf0006f536">FUSE_CAP_FLOCK_LOCKS</a>) {</div><div class="line"> <span class="keywordflow">if</span> (lo->debug)</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_init: activating flock locks\n"</span>);</div><div class="line"> conn-><a class="code" href="structfuse__conn__info.html#af45de81548b591f3004353a324e4e04d">want</a> |= <a class="code" href="fuse__common_8h.html#afd06393448dbb60668f5a3bf0006f536">FUSE_CAP_FLOCK_LOCKS</a>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_getattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keyword">struct </span>stat buf;</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"></div><div class="line"> (void) fi;</div><div class="line"></div><div class="line"> res = fstatat(lo_fd(req, ino), <span class="stringliteral">""</span>, &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">return</span> (<span class="keywordtype">void</span>) <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, errno);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ad28378dc569019c32acdb4995d70be18">fuse_reply_attr</a>(req, &buf, lo->timeout);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> utimensat_empty_nofollow(<span class="keyword">struct</span> lo_inode *inode,</div><div class="line"> <span class="keyword">const</span> <span class="keyword">struct</span> timespec *tv)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> res = utimensat(inode->fd, <span class="stringliteral">""</span>, tv,</div><div class="line"> AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (res == -1 && errno == EINVAL) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to set times on symlink. */</span></div><div class="line"> errno = EPERM;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">return</span> res;</div><div class="line"> }</div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> utimensat(AT_FDCWD, procname, tv, 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_setattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> stat *attr,</div><div class="line"> <span class="keywordtype">int</span> valid, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> <span class="keywordtype">int</span> ifd = inode->fd;</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_MODE) {</div><div class="line"> <span class="keywordflow">if</span> (fi) {</div><div class="line"> res = fchmod(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, attr->st_mode);</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, ifd);</div><div class="line"> res = chmod(procname, attr->st_mode);</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {</div><div class="line"> uid_t uid = (valid & FUSE_SET_ATTR_UID) ?</div><div class="line"> attr->st_uid : (uid_t) -1;</div><div class="line"> gid_t gid = (valid & FUSE_SET_ATTR_GID) ?</div><div class="line"> attr->st_gid : (gid_t) -1;</div><div class="line"></div><div class="line"> res = fchownat(ifd, <span class="stringliteral">""</span>, uid, gid,</div><div class="line"> AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_SIZE) {</div><div class="line"> <span class="keywordflow">if</span> (fi) {</div><div class="line"> res = ftruncate(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, attr->st_size);</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, ifd);</div><div class="line"> res = truncate(procname, attr->st_size);</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {</div><div class="line"> <span class="keyword">struct </span>timespec tv[2];</div><div class="line"></div><div class="line"> tv[0].tv_sec = 0;</div><div class="line"> tv[1].tv_sec = 0;</div><div class="line"> tv[0].tv_nsec = UTIME_OMIT;</div><div class="line"> tv[1].tv_nsec = UTIME_OMIT;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_ATIME_NOW)</div><div class="line"> tv[0].tv_nsec = UTIME_NOW;</div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_ATIME)</div><div class="line"> tv[0] = attr->st_atim;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_MTIME_NOW)</div><div class="line"> tv[1].tv_nsec = UTIME_NOW;</div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (valid & FUSE_SET_ATTR_MTIME)</div><div class="line"> tv[1] = attr->st_mtim;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (fi)</div><div class="line"> res = futimens(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, tv);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> res = utimensat_empty_nofollow(inode, tv);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> lo_getattr(req, ino, fi);</div><div class="line"></div><div class="line">out_err:</div><div class="line"> saverr = errno;</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>lo_inode *lo_find(<span class="keyword">struct</span> lo_data *lo, <span class="keyword">struct</span> stat *st)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span>lo_inode *p;</div><div class="line"> <span class="keyword">struct </span>lo_inode *ret = NULL;</div><div class="line"></div><div class="line"> pthread_mutex_lock(&lo->mutex);</div><div class="line"> <span class="keywordflow">for</span> (p = lo->root.next; p != &lo->root; p = p->next) {</div><div class="line"> <span class="keywordflow">if</span> (p->ino == st->st_ino && p->dev == st->st_dev) {</div><div class="line"> assert(p->refcount > 0);</div><div class="line"> ret = p;</div><div class="line"> ret->refcount++;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> pthread_mutex_unlock(&lo->mutex);</div><div class="line"> <span class="keywordflow">return</span> ret;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> lo_do_lookup(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> *e)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> newfd;</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode;</div><div class="line"></div><div class="line"> memset(e, 0, <span class="keyword">sizeof</span>(*e));</div><div class="line"> e-><a class="code" href="structfuse__entry__param.html#aa797a9f4152cae506ba479af8bbe2eb7">attr_timeout</a> = lo->timeout;</div><div class="line"> e-><a class="code" href="structfuse__entry__param.html#a281b39b72e7ec574ba40d7341fd22c1d">entry_timeout</a> = lo->timeout;</div><div class="line"></div><div class="line"> newfd = openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (newfd == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> res = fstatat(newfd, <span class="stringliteral">""</span>, &e-><a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> inode = lo_find(lo_data(req), &e-><a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>);</div><div class="line"> <span class="keywordflow">if</span> (inode) {</div><div class="line"> close(newfd);</div><div class="line"> newfd = -1;</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> <span class="keyword">struct </span>lo_inode *prev, *next;</div><div class="line"></div><div class="line"> saverr = ENOMEM;</div><div class="line"> inode = calloc(1, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> lo_inode));</div><div class="line"> <span class="keywordflow">if</span> (!inode)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> inode->is_symlink = S_ISLNK(e-><a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>.st_mode);</div><div class="line"> inode->refcount = 1;</div><div class="line"> inode->fd = newfd;</div><div class="line"> inode->ino = e-><a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>.st_ino;</div><div class="line"> inode->dev = e-><a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>.st_dev;</div><div class="line"></div><div class="line"> pthread_mutex_lock(&lo->mutex);</div><div class="line"> prev = &lo->root;</div><div class="line"> next = prev->next;</div><div class="line"> next->prev = inode;</div><div class="line"> inode->next = next;</div><div class="line"> inode->prev = prev;</div><div class="line"> prev->next = inode;</div><div class="line"> pthread_mutex_unlock(&lo->mutex);</div><div class="line"> }</div><div class="line"> e-><a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a> = (uintptr_t) inode;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">" %lli/%s -> %lli\n"</span>,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) parent, name, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> long) e-><a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a>);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line"></div><div class="line">out_err:</div><div class="line"> saverr = errno;</div><div class="line"> <span class="keywordflow">if</span> (newfd != -1)</div><div class="line"> close(newfd);</div><div class="line"> <span class="keywordflow">return</span> saverr;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_lookup(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> e;</div><div class="line"> <span class="keywordtype">int</span> err;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_lookup(parent=%"</span> PRIu64 <span class="stringliteral">", name=%s)\n"</span>,</div><div class="line"> parent, name);</div><div class="line"></div><div class="line"> err = lo_do_lookup(req, parent, name, &e);</div><div class="line"> <span class="keywordflow">if</span> (err)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, err);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a672c45e126cd240f4bcd59bf9b7e3708">fuse_reply_entry</a>(req, &e);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_mknod_symlink(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *name, mode_t mode, dev_t rdev,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *link)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> newfd = -1;</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode;</div><div class="line"> <span class="keyword">struct </span>lo_inode *dir = lo_inode(req, parent);</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> e;</div><div class="line"></div><div class="line"> saverr = ENOMEM;</div><div class="line"> inode = calloc(1, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> lo_inode));</div><div class="line"> <span class="keywordflow">if</span> (!inode)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (S_ISDIR(mode))</div><div class="line"> res = mkdirat(dir->fd, name, mode);</div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (S_ISLNK(mode))</div><div class="line"> res = symlinkat(link, dir->fd, name);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> res = mknodat(dir->fd, name, mode, rdev);</div><div class="line"> saverr = errno;</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> saverr = lo_do_lookup(req, parent, name, &e);</div><div class="line"> <span class="keywordflow">if</span> (saverr)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">" %lli/%s -> %lli\n"</span>,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) parent, name, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) e.<a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a>);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a672c45e126cd240f4bcd59bf9b7e3708">fuse_reply_entry</a>(req, &e);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">out:</div><div class="line"> <span class="keywordflow">if</span> (newfd != -1)</div><div class="line"> close(newfd);</div><div class="line"> free(inode);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_mknod(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *name, mode_t mode, dev_t rdev)</div><div class="line">{</div><div class="line"> lo_mknod_symlink(req, parent, name, mode, rdev, NULL);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_mkdir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> mode_t mode)</div><div class="line">{</div><div class="line"> lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_symlink(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <span class="keyword">const</span> <span class="keywordtype">char</span> *link,</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> linkat_empty_nofollow(<span class="keyword">struct</span> lo_inode *inode, <span class="keywordtype">int</span> dfd,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> res = linkat(inode->fd, <span class="stringliteral">""</span>, dfd, name, AT_EMPTY_PATH);</div><div class="line"> <span class="keywordflow">if</span> (res == -1 && (errno == ENOENT || errno == EINVAL)) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to hard-link a symlink. */</span></div><div class="line"> errno = EPERM;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">return</span> res;</div><div class="line"> }</div><div class="line"></div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> linkat(AT_FDCWD, procname, dfd, name, AT_SYMLINK_FOLLOW);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_link(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> e;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"></div><div class="line"> memset(&e, 0, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> <a class="code" href="structfuse__entry__param.html">fuse_entry_param</a>));</div><div class="line"> e.<a class="code" href="structfuse__entry__param.html#aa797a9f4152cae506ba479af8bbe2eb7">attr_timeout</a> = lo->timeout;</div><div class="line"> e.<a class="code" href="structfuse__entry__param.html#a281b39b72e7ec574ba40d7341fd22c1d">entry_timeout</a> = lo->timeout;</div><div class="line"></div><div class="line"> res = linkat_empty_nofollow(inode, lo_fd(req, parent), name);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> res = fstatat(inode->fd, <span class="stringliteral">""</span>, &e.<a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> pthread_mutex_lock(&lo->mutex);</div><div class="line"> inode->refcount++;</div><div class="line"> pthread_mutex_unlock(&lo->mutex);</div><div class="line"> e.<a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a> = (uintptr_t) inode;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">" %lli/%s -> %lli\n"</span>,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) parent, name,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> long) e.<a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a>);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a672c45e126cd240f4bcd59bf9b7e3708">fuse_reply_entry</a>(req, &e);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">out_err:</div><div class="line"> saverr = errno;</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_rmdir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_rename(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> newparent, <span class="keyword">const</span> <span class="keywordtype">char</span> *newname,</div><div class="line"> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> flags)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (flags) {</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, EINVAL);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> res = renameat(lo_fd(req, parent), name,</div><div class="line"> lo_fd(req, newparent), newname);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_unlink(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> res = unlinkat(lo_fd(req, parent), name, 0);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> unref_inode(<span class="keyword">struct</span> lo_data *lo, <span class="keyword">struct</span> lo_inode *inode, uint64_t n)</div><div class="line">{</div><div class="line"> <span class="keywordflow">if</span> (!inode)</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line"> pthread_mutex_lock(&lo->mutex);</div><div class="line"> assert(inode->refcount >= n);</div><div class="line"> inode->refcount -= n;</div><div class="line"> <span class="keywordflow">if</span> (!inode->refcount) {</div><div class="line"> <span class="keyword">struct </span>lo_inode *prev, *next;</div><div class="line"></div><div class="line"> prev = inode->prev;</div><div class="line"> next = inode->next;</div><div class="line"> next->prev = prev;</div><div class="line"> prev->next = next;</div><div class="line"></div><div class="line"> pthread_mutex_unlock(&lo->mutex);</div><div class="line"> close(inode->fd);</div><div class="line"> free(inode);</div><div class="line"></div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> pthread_mutex_unlock(&lo->mutex);</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_forget_one(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, uint64_t nlookup)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req)) {</div><div class="line"> fprintf(stderr, <span class="stringliteral">" forget %lli %lli -%lli\n"</span>,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) ino,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) inode->refcount,</div><div class="line"> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span>) nlookup);</div><div class="line"> }</div><div class="line"></div><div class="line"> unref_inode(lo, inode, nlookup);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_forget(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, uint64_t nlookup)</div><div class="line">{</div><div class="line"> lo_forget_one(req, ino, nlookup);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a85ae91390a6704dc26f8d80fed7d5678">fuse_reply_none</a>(req);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_forget_multi(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <span class="keywordtype">size_t</span> count,</div><div class="line"> <span class="keyword">struct</span> fuse_forget_data *forgets)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> i;</div><div class="line"></div><div class="line"> <span class="keywordflow">for</span> (i = 0; i < count; i++)</div><div class="line"> lo_forget_one(req, forgets[i].ino, forgets[i].nlookup);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a85ae91390a6704dc26f8d80fed7d5678">fuse_reply_none</a>(req);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_readlink(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino)</div><div class="line">{</div><div class="line"> <span class="keywordtype">char</span> buf[PATH_MAX + 1];</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> res = readlinkat(lo_fd(req, ino), <span class="stringliteral">""</span>, buf, <span class="keyword">sizeof</span>(buf));</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <span class="keywordflow">return</span> (<span class="keywordtype">void</span>) <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, errno);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (res == <span class="keyword">sizeof</span>(buf))</div><div class="line"> <span class="keywordflow">return</span> (<span class="keywordtype">void</span>) <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, ENAMETOOLONG);</div><div class="line"></div><div class="line"> buf[res] = <span class="charliteral">'\0'</span>;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a5a5872d7f73f0bd593e00788a4c7bbb7">fuse_reply_readlink</a>(req, buf);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">struct </span>lo_dirp {</div><div class="line"> <span class="keywordtype">int</span> fd;</div><div class="line"> DIR *dp;</div><div class="line"> <span class="keyword">struct </span>dirent *entry;</div><div class="line"> off_t offset;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>lo_dirp *lo_dirp(<span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> (<span class="keyword">struct</span> lo_dirp *) (uintptr_t) fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_opendir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> error = ENOMEM;</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"> <span class="keyword">struct </span>lo_dirp *d = calloc(1, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> lo_dirp));</div><div class="line"> <span class="keywordflow">if</span> (d == NULL)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> d->fd = openat(lo_fd(req, ino), <span class="stringliteral">"."</span>, O_RDONLY);</div><div class="line"> <span class="keywordflow">if</span> (d->fd == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_errno;</div><div class="line"></div><div class="line"> d->dp = fdopendir(d->fd);</div><div class="line"> <span class="keywordflow">if</span> (d->dp == NULL)</div><div class="line"> <span class="keywordflow">goto</span> out_errno;</div><div class="line"></div><div class="line"> d->offset = 0;</div><div class="line"> d->entry = NULL;</div><div class="line"></div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a> = (uintptr_t) d;</div><div class="line"> <span class="keywordflow">if</span> (lo->cache == CACHE_ALWAYS)</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a23a64eaecbf83f99aba8ee79e6de2780">keep_cache</a> = 1;</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a170f8c6b953d70928e83bcecee43bfdc">fuse_reply_open</a>(req, fi);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">out_errno:</div><div class="line"> error = errno;</div><div class="line">out_err:</div><div class="line"> <span class="keywordflow">if</span> (d) {</div><div class="line"> <span class="keywordflow">if</span> (d->fd != -1)</div><div class="line"> close(d->fd);</div><div class="line"> free(d);</div><div class="line"> }</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, error);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> is_dot_or_dotdot(<span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> name[0] == <span class="charliteral">'.'</span> && (name[1] == <span class="charliteral">'\0'</span> ||</div><div class="line"> (name[1] == <span class="charliteral">'.'</span> && name[2] == <span class="charliteral">'\0'</span>));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_do_readdir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">size_t</span> size,</div><div class="line"> off_t offset, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi, <span class="keywordtype">int</span> plus)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span>lo_dirp *d = lo_dirp(fi);</div><div class="line"> <span class="keywordtype">char</span> *buf;</div><div class="line"> <span class="keywordtype">char</span> *p;</div><div class="line"> <span class="keywordtype">size_t</span> rem = size;</div><div class="line"> <span class="keywordtype">int</span> err;</div><div class="line"></div><div class="line"> (void) ino;</div><div class="line"></div><div class="line"> buf = calloc(1, size);</div><div class="line"> <span class="keywordflow">if</span> (!buf) {</div><div class="line"> err = ENOMEM;</div><div class="line"> <span class="keywordflow">goto</span> error;</div><div class="line"> }</div><div class="line"> p = buf;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (offset != d->offset) {</div><div class="line"> seekdir(d->dp, offset);</div><div class="line"> d->entry = NULL;</div><div class="line"> d->offset = offset;</div><div class="line"> }</div><div class="line"> <span class="keywordflow">while</span> (1) {</div><div class="line"> <span class="keywordtype">size_t</span> entsize;</div><div class="line"> off_t nextoff;</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *name;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (!d->entry) {</div><div class="line"> errno = 0;</div><div class="line"> d->entry = readdir(d->dp);</div><div class="line"> <span class="keywordflow">if</span> (!d->entry) {</div><div class="line"> <span class="keywordflow">if</span> (errno) { <span class="comment">// Error</span></div><div class="line"> err = errno;</div><div class="line"> <span class="keywordflow">goto</span> error;</div><div class="line"> } <span class="keywordflow">else</span> { <span class="comment">// End of stream</span></div><div class="line"> <span class="keywordflow">break</span>; </div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> nextoff = d->entry->d_off;</div><div class="line"> name = d->entry->d_name;</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> entry_ino = 0;</div><div class="line"> <span class="keywordflow">if</span> (plus) {</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> e;</div><div class="line"> <span class="keywordflow">if</span> (is_dot_or_dotdot(name)) {</div><div class="line"> e = (<span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a>) {</div><div class="line"> .<a class="code" href="structfuse__entry__param.html#adcdee37c96ad18380a47cdbe96a323b9">attr</a>.st_ino = d->entry->d_ino,</div><div class="line"> .attr.st_mode = d->entry->d_type << 12,</div><div class="line"> };</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> err = lo_do_lookup(req, ino, name, &e);</div><div class="line"> <span class="keywordflow">if</span> (err)</div><div class="line"> <span class="keywordflow">goto</span> error;</div><div class="line"> entry_ino = e.<a class="code" href="structfuse__entry__param.html#a285ba89754871772d940fa4fb736bce3">ino</a>;</div><div class="line"> }</div><div class="line"></div><div class="line"> entsize = <a class="code" href="fuse__lowlevel_8h.html#a34f3f1beebacab5f717d95baf832a8a5">fuse_add_direntry_plus</a>(req, p, rem, name,</div><div class="line"> &e, nextoff);</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> <span class="keyword">struct </span>stat st = {</div><div class="line"> .st_ino = d->entry->d_ino,</div><div class="line"> .st_mode = d->entry->d_type << 12,</div><div class="line"> };</div><div class="line"> entsize = <a class="code" href="fuse__lowlevel_8h.html#ad1957bcc8ece8c90f16c42c4daf3053f">fuse_add_direntry</a>(req, p, rem, name,</div><div class="line"> &st, nextoff);</div><div class="line"> }</div><div class="line"> <span class="keywordflow">if</span> (entsize > rem) {</div><div class="line"> <span class="keywordflow">if</span> (entry_ino != 0) </div><div class="line"> lo_forget_one(req, entry_ino, 1);</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> }</div><div class="line"> </div><div class="line"> p += entsize;</div><div class="line"> rem -= entsize;</div><div class="line"></div><div class="line"> d->entry = NULL;</div><div class="line"> d->offset = nextoff;</div><div class="line"> }</div><div class="line"></div><div class="line"> err = 0;</div><div class="line">error:</div><div class="line"> <span class="comment">// If there's an error, we can only signal it if we haven't stored</span></div><div class="line"> <span class="comment">// any entries yet - otherwise we'd end up with wrong lookup</span></div><div class="line"> <span class="comment">// counts for the entries that are already in the buffer. So we</span></div><div class="line"> <span class="comment">// return what we've collected until that point.</span></div><div class="line"> <span class="keywordflow">if</span> (err && rem == size)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, err);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a300a88b63ab7c8ca92853a97486448c0">fuse_reply_buf</a>(req, buf, size - rem);</div><div class="line"> free(buf);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_readdir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">size_t</span> size,</div><div class="line"> off_t offset, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> lo_do_readdir(req, ino, size, offset, fi, 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_readdirplus(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">size_t</span> size,</div><div class="line"> off_t offset, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> lo_do_readdir(req, ino, size, offset, fi, 1);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_releasedir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span>lo_dirp *d = lo_dirp(fi);</div><div class="line"> (void) ino;</div><div class="line"> closedir(d->dp);</div><div class="line"> free(d);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_create(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> parent, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> mode_t mode, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> fd;</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__entry__param.html">fuse_entry_param</a> e;</div><div class="line"> <span class="keywordtype">int</span> err;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_create(parent=%"</span> PRIu64 <span class="stringliteral">", name=%s)\n"</span>,</div><div class="line"> parent, name);</div><div class="line"></div><div class="line"> fd = openat(lo_fd(req, parent), name,</div><div class="line"> (fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> | O_CREAT) & ~O_NOFOLLOW, mode);</div><div class="line"> <span class="keywordflow">if</span> (fd == -1)</div><div class="line"> <span class="keywordflow">return</span> (<span class="keywordtype">void</span>) <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, errno);</div><div class="line"></div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a> = fd;</div><div class="line"></div><div class="line"> err = lo_do_lookup(req, parent, name, &e);</div><div class="line"> <span class="keywordflow">if</span> (err)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, err);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#abea78d22349198f8370d7cb91fbf05ed">fuse_reply_create</a>(req, &e, fi);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_fsyncdir(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">int</span> datasync,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keywordtype">int</span> fd = dirfd(lo_dirp(fi)->dp);</div><div class="line"> (void) ino;</div><div class="line"> <span class="keywordflow">if</span> (datasync)</div><div class="line"> res = fdatasync(fd);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> res = fsync(fd);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_open(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> fd;</div><div class="line"> <span class="keywordtype">char</span> buf[64];</div><div class="line"> <span class="keyword">struct </span>lo_data *lo = lo_data(req);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_open(ino=%"</span> PRIu64 <span class="stringliteral">", flags=%d)\n"</span>,</div><div class="line"> ino, fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a>);</div><div class="line"></div><div class="line"> <span class="comment">/* With writeback cache, kernel may send read requests even</span></div><div class="line"><span class="comment"> when userspace opened write-only */</span></div><div class="line"> <span class="keywordflow">if</span> (lo->writeback && (fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> & O_ACCMODE) == O_WRONLY) {</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> &= ~O_ACCMODE;</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> |= O_RDWR;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/* With writeback cache, O_APPEND is handled by the kernel.</span></div><div class="line"><span class="comment"> This breaks atomicity (since the file may change in the</span></div><div class="line"><span class="comment"> underlying filesystem, so that the kernel's idea of the</span></div><div class="line"><span class="comment"> end of the file isn't accurate anymore). In this example,</span></div><div class="line"><span class="comment"> we just accept that. A more rigorous filesystem may want</span></div><div class="line"><span class="comment"> to return an error here */</span></div><div class="line"> <span class="keywordflow">if</span> (lo->writeback && (fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> & O_APPEND))</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> &= ~O_APPEND;</div><div class="line"></div><div class="line"> sprintf(buf, <span class="stringliteral">"/proc/self/fd/%i"</span>, lo_fd(req, ino));</div><div class="line"> fd = open(buf, fi-><a class="code" href="structfuse__file__info.html#ae7d31802727be19670193a411647bca5">flags</a> & ~O_NOFOLLOW);</div><div class="line"> <span class="keywordflow">if</span> (fd == -1)</div><div class="line"> <span class="keywordflow">return</span> (<span class="keywordtype">void</span>) <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, errno);</div><div class="line"></div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a> = fd;</div><div class="line"> <span class="keywordflow">if</span> (lo->cache == CACHE_NEVER)</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a03b59a10e62963d9affa34ad78bd144a">direct_io</a> = 1;</div><div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (lo->cache == CACHE_ALWAYS)</div><div class="line"> fi-><a class="code" href="structfuse__file__info.html#a23a64eaecbf83f99aba8ee79e6de2780">keep_cache</a> = 1;</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a170f8c6b953d70928e83bcecee43bfdc">fuse_reply_open</a>(req, fi);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_release(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> (void) ino;</div><div class="line"></div><div class="line"> close(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_flush(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> (void) ino;</div><div class="line"> res = close(dup(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>));</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_fsync(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">int</span> datasync,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> (void) ino;</div><div class="line"> <span class="keywordflow">if</span> (datasync)</div><div class="line"> res = fdatasync(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> res = fsync(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_read(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">size_t</span> size,</div><div class="line"> off_t offset, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__bufvec.html">fuse_bufvec</a> buf = FUSE_BUFVEC_INIT(size);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_read(ino=%"</span> PRIu64 <span class="stringliteral">", size=%zd, "</span></div><div class="line"> <span class="stringliteral">"off=%lu)\n"</span>, ino, size, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) offset);</div><div class="line"></div><div class="line"> buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a1928e204554f2d37cb8dac28a8a2f28c">flags</a> = <a class="code" href="fuse__common_8h.html#a5e36b839c4dbf0439bd85b61c7213a58affd5b3b7e9cdd5f89b3126eea96e033b">FUSE_BUF_IS_FD</a> | <a class="code" href="fuse__common_8h.html#a5e36b839c4dbf0439bd85b61c7213a58ad67d5c6075febad0594f06d46d02bfa9">FUSE_BUF_FD_SEEK</a>;</div><div class="line"> buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a62b2ae82904ac4355142984b9dd90d68">fd</a> = fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>;</div><div class="line"> buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a8de23b7869b06b9a9caef6beb7c9e88e">pos</a> = offset;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a1242694fe0fb6e253a88b57795987302">fuse_reply_data</a>(req, &buf, <a class="code" href="fuse__common_8h.html#aec0ad71a3e8c357ebe7e87cdecbdbe18af239e556066a5d73b3ff542216b157b9">FUSE_BUF_SPLICE_MOVE</a>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_write_buf(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__bufvec.html">fuse_bufvec</a> *in_buf, off_t off,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> (void) ino;</div><div class="line"> ssize_t res;</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__bufvec.html">fuse_bufvec</a> out_buf = FUSE_BUFVEC_INIT(<a class="code" href="fuse__common_8h.html#a4327f41b2fe1ca84151b407169bd86c0">fuse_buf_size</a>(in_buf));</div><div class="line"></div><div class="line"> out_buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a1928e204554f2d37cb8dac28a8a2f28c">flags</a> = <a class="code" href="fuse__common_8h.html#a5e36b839c4dbf0439bd85b61c7213a58affd5b3b7e9cdd5f89b3126eea96e033b">FUSE_BUF_IS_FD</a> | <a class="code" href="fuse__common_8h.html#a5e36b839c4dbf0439bd85b61c7213a58ad67d5c6075febad0594f06d46d02bfa9">FUSE_BUF_FD_SEEK</a>;</div><div class="line"> out_buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a62b2ae82904ac4355142984b9dd90d68">fd</a> = fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>;</div><div class="line"> out_buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#a8de23b7869b06b9a9caef6beb7c9e88e">pos</a> = <a class="code" href="structfuse__bufvec.html#a0fbb583168d52562f0f848562ecf63bc">off</a>;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_write(ino=%"</span> PRIu64 <span class="stringliteral">", size=%zd, off=%lu)\n"</span>,</div><div class="line"> ino, out_buf.<a class="code" href="structfuse__bufvec.html#a754caca61fdf8107d28b510505a033bb">buf</a>[0].<a class="code" href="structfuse__buf.html#afb58c1e18f434d1d4edb784d00e2e13d">size</a>, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) off);</div><div class="line"></div><div class="line"> res = <a class="code" href="fuse__common_8h.html#a9ca301390fb5e85b85153abb1891a3f7">fuse_buf_copy</a>(&out_buf, in_buf, 0);</div><div class="line"> <span class="keywordflow">if</span>(res < 0)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, -res);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#aa3cfa73f61d6ef461ab5a3fbf859eb97">fuse_reply_write</a>(req, (<span class="keywordtype">size_t</span>) res);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_statfs(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> <span class="keyword">struct </span>statvfs stbuf;</div><div class="line"></div><div class="line"> res = fstatvfs(lo_fd(req, ino), &stbuf);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, errno);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#aa1d95ec3ca674253baac3639ea10f0ff">fuse_reply_statfs</a>(req, &stbuf);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_fallocate(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">int</span> mode,</div><div class="line"> off_t offset, off_t length, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> err;</div><div class="line"> (void) ino;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (mode) {</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, EOPNOTSUPP);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> err = posix_fallocate(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, offset, length);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, err);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_flock(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi,</div><div class="line"> <span class="keywordtype">int</span> op)</div><div class="line">{</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"> (void) ino;</div><div class="line"></div><div class="line"> res = flock(fi-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, op);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, res == -1 ? errno : 0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_getxattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> <span class="keywordtype">size_t</span> size)</div><div class="line">{</div><div class="line"> <span class="keywordtype">char</span> *value = NULL;</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> ssize_t ret;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"></div><div class="line"> saverr = ENOSYS;</div><div class="line"> <span class="keywordflow">if</span> (!lo_data(req)->xattr)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req)) {</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_getxattr(ino=%"</span> PRIu64 <span class="stringliteral">", name=%s size=%zd)\n"</span>,</div><div class="line"> ino, name, size);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to getxattr on symlink. */</span></div><div class="line"> saverr = EPERM;</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"> }</div><div class="line"></div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (size) {</div><div class="line"> value = malloc(size);</div><div class="line"> <span class="keywordflow">if</span> (!value)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> ret = getxattr(procname, name, value, size);</div><div class="line"> <span class="keywordflow">if</span> (ret == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> saverr = 0;</div><div class="line"> <span class="keywordflow">if</span> (ret == 0)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a300a88b63ab7c8ca92853a97486448c0">fuse_reply_buf</a>(req, value, ret);</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> ret = getxattr(procname, name, NULL, 0);</div><div class="line"> <span class="keywordflow">if</span> (ret == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#afed32e5d3e1f54d390103f79ebb8bd42">fuse_reply_xattr</a>(req, ret);</div><div class="line"> }</div><div class="line">out_free:</div><div class="line"> free(value);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">out_err:</div><div class="line"> saverr = errno;</div><div class="line">out:</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line"> <span class="keywordflow">goto</span> out_free;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_listxattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keywordtype">size_t</span> size)</div><div class="line">{</div><div class="line"> <span class="keywordtype">char</span> *value = NULL;</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> ssize_t ret;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"></div><div class="line"> saverr = ENOSYS;</div><div class="line"> <span class="keywordflow">if</span> (!lo_data(req)->xattr)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req)) {</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_listxattr(ino=%"</span> PRIu64 <span class="stringliteral">", size=%zd)\n"</span>,</div><div class="line"> ino, size);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to listxattr on symlink. */</span></div><div class="line"> saverr = EPERM;</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"> }</div><div class="line"></div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (size) {</div><div class="line"> value = malloc(size);</div><div class="line"> <span class="keywordflow">if</span> (!value)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> ret = listxattr(procname, value, size);</div><div class="line"> <span class="keywordflow">if</span> (ret == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"> saverr = 0;</div><div class="line"> <span class="keywordflow">if</span> (ret == 0)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a300a88b63ab7c8ca92853a97486448c0">fuse_reply_buf</a>(req, value, ret);</div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> ret = listxattr(procname, NULL, 0);</div><div class="line"> <span class="keywordflow">if</span> (ret == -1)</div><div class="line"> <span class="keywordflow">goto</span> out_err;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#afed32e5d3e1f54d390103f79ebb8bd42">fuse_reply_xattr</a>(req, ret);</div><div class="line"> }</div><div class="line">out_free:</div><div class="line"> free(value);</div><div class="line"> <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">out_err:</div><div class="line"> saverr = errno;</div><div class="line">out:</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line"> <span class="keywordflow">goto</span> out_free;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_setxattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"> <span class="keyword">const</span> <span class="keywordtype">char</span> *value, <span class="keywordtype">size_t</span> size, <span class="keywordtype">int</span> flags)</div><div class="line">{</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> ssize_t ret;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"></div><div class="line"> saverr = ENOSYS;</div><div class="line"> <span class="keywordflow">if</span> (!lo_data(req)->xattr)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req)) {</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_setxattr(ino=%"</span> PRIu64 <span class="stringliteral">", name=%s value=%s size=%zd)\n"</span>,</div><div class="line"> ino, name, value, size);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to setxattr on symlink. */</span></div><div class="line"> saverr = EPERM;</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"> }</div><div class="line"></div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> ret = setxattr(procname, name, value, size, flags);</div><div class="line"> saverr = ret == -1 ? errno : 0;</div><div class="line"></div><div class="line">out:</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_removexattr(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino, <span class="keyword">const</span> <span class="keywordtype">char</span> *name)</div><div class="line">{</div><div class="line"> <span class="keywordtype">char</span> procname[64];</div><div class="line"> <span class="keyword">struct </span>lo_inode *inode = lo_inode(req, ino);</div><div class="line"> ssize_t ret;</div><div class="line"> <span class="keywordtype">int</span> saverr;</div><div class="line"></div><div class="line"> saverr = ENOSYS;</div><div class="line"> <span class="keywordflow">if</span> (!lo_data(req)->xattr)</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req)) {</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_removexattr(ino=%"</span> PRIu64 <span class="stringliteral">", name=%s)\n"</span>,</div><div class="line"> ino, name);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (inode->is_symlink) {</div><div class="line"> <span class="comment">/* Sorry, no race free way to setxattr on symlink. */</span></div><div class="line"> saverr = EPERM;</div><div class="line"> <span class="keywordflow">goto</span> out;</div><div class="line"> }</div><div class="line"></div><div class="line"> sprintf(procname, <span class="stringliteral">"/proc/self/fd/%i"</span>, inode->fd);</div><div class="line"></div><div class="line"> ret = removexattr(procname, name);</div><div class="line"> saverr = ret == -1 ? errno : 0;</div><div class="line"></div><div class="line">out:</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, saverr);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef HAVE_COPY_FILE_RANGE</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> lo_copy_file_range(<a class="code" href="fuse__lowlevel_8h.html#a33e2aa4a8905a05397292ae047cd2257">fuse_req_t</a> req, <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino_in, off_t off_in,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi_in,</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ad119a72f00b4cd2e4a500fd3364ae1e2">fuse_ino_t</a> ino_out, off_t off_out,</div><div class="line"> <span class="keyword">struct</span> <a class="code" href="structfuse__file__info.html">fuse_file_info</a> *fi_out, <span class="keywordtype">size_t</span> len,</div><div class="line"> <span class="keywordtype">int</span> flags)</div><div class="line">{</div><div class="line"> ssize_t res;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo_debug(req))</div><div class="line"> fprintf(stderr, <span class="stringliteral">"lo_copy_file_range(ino=%"</span> PRIu64 <span class="stringliteral">"/fd=%lu, "</span></div><div class="line"> <span class="stringliteral">"off=%lu, ino=%"</span> PRIu64 <span class="stringliteral">"/fd=%lu, "</span></div><div class="line"> <span class="stringliteral">"off=%lu, size=%zd, flags=0x%x)\n"</span>,</div><div class="line"> ino_in, fi_in-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, off_in, ino_out, fi_out-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, off_out,</div><div class="line"> len, flags);</div><div class="line"></div><div class="line"> res = copy_file_range(fi_in-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, &off_in, fi_out-><a class="code" href="structfuse__file__info.html#a45314d0b92a8d4c9de33d996aa59ada8">fh</a>, &off_out, len,</div><div class="line"> flags);</div><div class="line"> <span class="keywordflow">if</span> (res < 0)</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a2553c03f9a63c75e609e67f90a3a5d88">fuse_reply_err</a>(req, -errno);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#aa3cfa73f61d6ef461ab5a3fbf859eb97">fuse_reply_write</a>(req, res);</div><div class="line">}</div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span><a class="code" href="structfuse__lowlevel__ops.html">fuse_lowlevel_ops</a> lo_oper = {</div><div class="line"> .<a class="code" href="structfuse__lowlevel__ops.html#aa8ed20e1d06c42a386404fba0d3e56b5">init</a> = lo_init,</div><div class="line"> .lookup = lo_lookup,</div><div class="line"> .mkdir = lo_mkdir,</div><div class="line"> .mknod = lo_mknod,</div><div class="line"> .symlink = lo_symlink,</div><div class="line"> .link = lo_link,</div><div class="line"> .unlink = lo_unlink,</div><div class="line"> .rmdir = lo_rmdir,</div><div class="line"> .rename = lo_rename,</div><div class="line"> .forget = lo_forget,</div><div class="line"> .forget_multi = lo_forget_multi,</div><div class="line"> .getattr = lo_getattr,</div><div class="line"> .setattr = lo_setattr,</div><div class="line"> .readlink = lo_readlink,</div><div class="line"> .opendir = lo_opendir,</div><div class="line"> .readdir = lo_readdir,</div><div class="line"> .readdirplus = lo_readdirplus,</div><div class="line"> .releasedir = lo_releasedir,</div><div class="line"> .fsyncdir = lo_fsyncdir,</div><div class="line"> .create = lo_create,</div><div class="line"> .open = lo_open,</div><div class="line"> .release = lo_release,</div><div class="line"> .flush = lo_flush,</div><div class="line"> .fsync = lo_fsync,</div><div class="line"> .read = lo_read,</div><div class="line"> .write_buf = lo_write_buf,</div><div class="line"> .statfs = lo_statfs,</div><div class="line"> .fallocate = lo_fallocate,</div><div class="line"> .flock = lo_flock,</div><div class="line"> .getxattr = lo_getxattr,</div><div class="line"> .listxattr = lo_listxattr,</div><div class="line"> .setxattr = lo_setxattr,</div><div class="line"> .removexattr = lo_removexattr,</div><div class="line"><span class="preprocessor">#ifdef HAVE_COPY_FILE_RANGE</span></div><div class="line"> .copy_file_range = lo_copy_file_range,</div><div class="line"><span class="preprocessor">#endif</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> *argv[])</div><div class="line">{</div><div class="line"> <span class="keyword">struct </span><a class="code" href="structfuse__args.html">fuse_args</a> args = <a class="code" href="fuse__opt_8h.html#a9bea40fe56b18be9aa110185ab7387ed">FUSE_ARGS_INIT</a>(argc, argv);</div><div class="line"> <span class="keyword">struct </span>fuse_session *se;</div><div class="line"> <span class="keyword">struct </span>fuse_cmdline_opts opts;</div><div class="line"> <span class="keyword">struct </span>lo_data lo = { .debug = 0,</div><div class="line"> .writeback = 0 };</div><div class="line"> <span class="keywordtype">int</span> ret = -1;</div><div class="line"></div><div class="line"> <span class="comment">/* Don't mask creation mode, kernel already did that */</span></div><div class="line"> umask(0);</div><div class="line"></div><div class="line"> pthread_mutex_init(&lo.mutex, NULL);</div><div class="line"> lo.root.next = lo.root.prev = &lo.root;</div><div class="line"> lo.root.fd = -1;</div><div class="line"> lo.cache = CACHE_NORMAL;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (<a class="code" href="fuse__lowlevel_8h.html#a8421a0cb3b6fb7013c7272c6997d1e08">fuse_parse_cmdline</a>(&args, &opts) != 0)</div><div class="line"> <span class="keywordflow">return</span> 1;</div><div class="line"> <span class="keywordflow">if</span> (opts.show_help) {</div><div class="line"> printf(<span class="stringliteral">"usage: %s [options] <mountpoint>\n\n"</span>, argv[0]);</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a7235e3a2d1c780d5e0beaee13c81529f">fuse_cmdline_help</a>();</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a990af0becaba1b5e45781d399720f85e">fuse_lowlevel_help</a>();</div><div class="line"> ret = 0;</div><div class="line"> <span class="keywordflow">goto</span> err_out1;</div><div class="line"> } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (opts.show_version) {</div><div class="line"> printf(<span class="stringliteral">"FUSE library version %s\n"</span>, <a class="code" href="fuse__common_8h.html#ac52e27388a7c16eb509173908e5eebd0">fuse_pkgversion</a>());</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#ac6e2d0fde62dcf4f0e57afeabeefd7b1">fuse_lowlevel_version</a>();</div><div class="line"> ret = 0;</div><div class="line"> <span class="keywordflow">goto</span> err_out1;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span>(opts.mountpoint == NULL) {</div><div class="line"> printf(<span class="stringliteral">"usage: %s [options] <mountpoint>\n"</span>, argv[0]);</div><div class="line"> printf(<span class="stringliteral">" %s --help\n"</span>, argv[0]);</div><div class="line"> ret = 1;</div><div class="line"> <span class="keywordflow">goto</span> err_out1;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (<a class="code" href="fuse__opt_8h.html#a539ef1f571c34f516c60c4cbe2901c0e">fuse_opt_parse</a>(&args, &lo, lo_opts, NULL)== -1)</div><div class="line"> <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line"> lo.debug = opts.debug;</div><div class="line"> lo.root.refcount = 2;</div><div class="line"> <span class="keywordflow">if</span> (lo.source) {</div><div class="line"> <span class="keyword">struct </span>stat stat;</div><div class="line"> <span class="keywordtype">int</span> res;</div><div class="line"></div><div class="line"> res = lstat(lo.source, &stat);</div><div class="line"> <span class="keywordflow">if</span> (res == -1)</div><div class="line"> err(1, <span class="stringliteral">"failed to stat source (\"%s\")"</span>, lo.source);</div><div class="line"> <span class="keywordflow">if</span> (!S_ISDIR(stat.st_mode))</div><div class="line"> errx(1, <span class="stringliteral">"source is not a directory"</span>);</div><div class="line"></div><div class="line"> } <span class="keywordflow">else</span> {</div><div class="line"> lo.source = <span class="stringliteral">"/"</span>;</div><div class="line"> }</div><div class="line"> lo.root.is_symlink = <span class="keyword">false</span>;</div><div class="line"> <span class="keywordflow">if</span> (!lo.timeout_set) {</div><div class="line"> <span class="keywordflow">switch</span> (lo.cache) {</div><div class="line"> <span class="keywordflow">case</span> CACHE_NEVER:</div><div class="line"> lo.timeout = 0.0;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line"> <span class="keywordflow">case</span> CACHE_NORMAL:</div><div class="line"> lo.timeout = 1.0;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line"> <span class="keywordflow">case</span> CACHE_ALWAYS:</div><div class="line"> lo.timeout = 86400.0;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> }</div><div class="line"> } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (lo.timeout < 0) {</div><div class="line"> errx(1, <span class="stringliteral">"timeout is negative (%lf)"</span>, lo.timeout);</div><div class="line"> }</div><div class="line"></div><div class="line"> lo.root.fd = open(lo.source, O_PATH);</div><div class="line"> <span class="keywordflow">if</span> (lo.root.fd == -1)</div><div class="line"> err(1, <span class="stringliteral">"open(\"%s\", O_PATH)"</span>, lo.source);</div><div class="line"></div><div class="line"> se = <a class="code" href="fuse__lowlevel_8h.html#a9ee52f81d0c63d9bd46b11314ba596cf">fuse_session_new</a>(&args, &lo_oper, <span class="keyword">sizeof</span>(lo_oper), &lo);</div><div class="line"> <span class="keywordflow">if</span> (se == NULL)</div><div class="line"> <span class="keywordflow">goto</span> err_out1;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (<a class="code" href="fuse__common_8h.html#a292dccc3c7b1799cb054efa2ba0c774b">fuse_set_signal_handlers</a>(se) != 0)</div><div class="line"> <span class="keywordflow">goto</span> err_out2;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (<a class="code" href="fuse__lowlevel_8h.html#aa6d77679a110582684e9ca2da623bbc2">fuse_session_mount</a>(se, opts.mountpoint) != 0)</div><div class="line"> <span class="keywordflow">goto</span> err_out3;</div><div class="line"></div><div class="line"> <a class="code" href="fuse__common_8h.html#af1857d2209952f49a762aff39f3cd8bd">fuse_daemonize</a>(opts.foreground);</div><div class="line"></div><div class="line"> <span class="comment">/* Block until ctrl+c or fusermount -u */</span></div><div class="line"> <span class="keywordflow">if</span> (opts.singlethread)</div><div class="line"> ret = <a class="code" href="fuse__lowlevel_8h.html#a5f1e538aa3287e251afbe985438c4249">fuse_session_loop</a>(se);</div><div class="line"> <span class="keywordflow">else</span></div><div class="line"> ret = fuse_session_loop_mt(se, opts.clone_fd);</div><div class="line"></div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a6c10d942751ddb214863a8b5e53de5e8">fuse_session_unmount</a>(se);</div><div class="line">err_out3:</div><div class="line"> <a class="code" href="fuse__common_8h.html#aeb674bbc11074c4fe520b952d6bfdd30">fuse_remove_signal_handlers</a>(se);</div><div class="line">err_out2:</div><div class="line"> <a class="code" href="fuse__lowlevel_8h.html#a08b5503c4e9656f9c4bc88331233cc65">fuse_session_destroy</a>(se);</div><div class="line">err_out1:</div><div class="line"> free(opts.mountpoint);</div><div class="line"> <a class="code" href="fuse__opt_8h.html#a2cdf272429ab3869a5162976141b287d">fuse_opt_free_args</a>(&args);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (lo.root.fd >= 0)</div><div class="line"> close(lo.root.fd);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> ret ? 1 : 0;</div><div class="line">}</div></div><!-- fragment -->
<p class="definition">Definition in file <a class="el" href="passthrough__ll_8c_source.html">passthrough_ll.c</a>.</p>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
</body>
</html>
|