fresh git tree for public release

we regretfully had to remove our git history for licensing reasons

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2010-10-11 14:59:26 -04:00
commit 0ad4db4fad
271 changed files with 71255 additions and 0 deletions

107
README.html Normal file
View file

@ -0,0 +1,107 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Windows NFS 4.1 Client Instructions</title>
<link rel="stylesheet" title="CITI Default" href="http://www.citi.umich.edu/format/citi.css" type="text/css"/>
<link rel="icon" href="http://www.citi.umich.edu/images/citilogo-16x16.png" type="image/png"/>
<link rel="shortcut icon" href="http://www.citi.umich.edu/images/citilogo-16x16.png" type="image/png"/>
<style type="text/css">
/*<![CDATA[*/
body { min-width: 600px; background-color: #DDDDFF; font-family: serif; }
#page { padding: 0 12px 0 12px; }
#content { margin: 12px 0 12px 0; padding: 8px; background-color: #FFFFFF; border: 1px solid #88A; }
#index { padding-right: 12px; float: right; background-color: #FFFFFF; border: 1px solid #88A; }
a { color: #0282b4; }
a:hover { color: #0244b4; }
h1 { font-size: 2em; text-align: center; background: none; }
h2 { margin: 24px 0 8px 0; font-variant: small-caps; border-bottom: 1px dashed #88A; }
h3 { margin-left: 8px; }
span.filename { font-weight: bold; }
span.code { font-family: Courier; }
/*]]>*/
</style>
</head>
<body>
<div id="page">
<h1>Windows NFS 4.1 Client Instructions</h1>
<div id="content">
<div id="index">
<ol>
<li><a href="#build">Building</a></li>
<li><a href="#install">Installation</a></li>
<li><a href="#mount">Mounting</a></li>
<li><a href="#cthon">Connectation</a></li>
<li><a href="#issues">Known Issues</a></li>
</ol>
</div>
<h2>1. <a name="build">Building</a></h2>
<h3>Requirements</h3>
<ul>
<li>ms-nfs41-client source code:
<br/><span class="code">&gt; git clone git://citi.umich.edu/projects/ms-nfs41-client.git</span></li>
<li>Windows Driver Development Kit (WinDDK 6000 or later)</li>
</ul>
<h3>Instructions</h3>
<ol>
<li>Open the WinDDK build environment for the target platform.</li>
<li>Change directory to <span class="filename">ms-nfs41-client</span> and type <span class="code">build</span>. The project should build without errors.</li>
</ol>
<h2>2. <a name="install">Installation</a></h2>
<h3>Requirements</h3>
<ul>
<li>ms-nfs41-client binaries: <span class="filename">nfs41_driver.sys</span>, <span class="filename">nfs41_np.dll</span>, <span class="filename">libtirpc.dll</span>, <span class="filename">nfs_install.exe</span>, <span class="filename">nfsd.exe</span>, <span class="filename">nfs_mount.exe</span></li>
<li>ms-nfs41-client configuration files: <span class="filename">nfs41rdr.inf</span>, <span class="filename">install.bat</span>, <span class="filename">uninstall.bat</span>, <span class="filename">etc_netconfig</span></li>
<li>a certificate for test signing (<a href="http://msdn.microsoft.com/en-us/library/aa906283.aspx" title="Test-Signing a Driver File">http://msdn.microsoft.com/en-us/library/aa906283.aspx</a>)</li>
</ul>
<h3>Instructions</h3>
<ol>
<li>Copy or extract all ms-nfs41-client binaries and configuration files into a directory that's convenient for testing.</li>
<li>Open an Administrator command prompt in this directory.</li>
<li>Test sign <span class="filename">nfs41_driver.sys</span>.</li>
<li>Install the driver and update the registry:
<br/><span class="code">&gt; install.bat</span></li>
<li>Copy the libtirpc configuration:
<br/><span class="code">&gt; mkdir C:\etc</span>
<br/><span class="code">&gt; copy etc_netconfig C:\etc\netconfig</span></li>
<li>Allow windows to load test-signed drivers:
<br/><span class="code">&gt; bcdedit /set testsigning on</span></li>
<li>Install the certificate used for test signing to the 'Trusted Root Certificate Authorities' store.</li>
<li>Open the Control Panel, navigate to User Accounts, and disable User Account Control (see <a href="#issues">5. Known Issues</a>).</li>
<li>Reboot.</li>
</ol>
<h2>3. <a name="mount">Mounting</a></h2>
<h3>Instructions</h3>
<ol>
<li>Run <span class="filename">nfsd.exe</span></li>
<li>Open a command prompt and run <span class="filename">nfs_mount.exe</span> to mount a share:
<br/><span class="code">&gt; nfs_mount.exe Z: nfs.citi.umich.edu:\</span></li>
<li>You can later unmount with:
<br/><span class="code">&gt; nfs_mount.exe -d Z</span></li>
</ol>
<h2>4. <a name="cthon">Connectathon</a></h2>
<h3>Requirements</h3>
<ul>
<li><a href="http://www.cygwin.com" title="www.cygwin.com">Cygwin</a>, including packages gcc-core, make, sunrpc, time</li>
<li>ms-nfs41-client source code (ported tests are located in <span class="filename">ms-nfs41-client\tests\cthon04</span>)</li>
</ul>
<h3>Instructions</h3>
<ol>
<li>Copy <span class="filename">ms-nfs41-client\tests\cthon04</span> into a directory that's convenient for testing.</li>
<li>Open a cygwin shell, and change directory to cthon04.</li>
<li>Run the test suite on a mounted directory:
<br/><span class="code">&gt; ./runtests -a -t z:/testdir</span></li>
</ol>
<h2>5. <a name="issues">Known Issues</a></h2>
<ul>
<li>Mounts must be obtained through nfs_mount.exe, and not via 'net use' or 'Map Network Drive'.</li>
<li>When nfs_mount.exe is run without arguments, it does not properly list mounted drives.</li>
<li>If nfsd.exe is restarted while a drive is mapped, that drive needs to be remounted before further use.</li>
<li>Symbolic links are not supported. Connectathon's basic test8 will not pass.</li>
<li>Does not properly handle renaming a file on top of an existing open file- the existing file is removed on rename, and not preserved until last close.</li>
</ul>
</div>
</div>
</body>
</html>

7
build.vc10/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
# exclude all build files by default
*
# allow visual studio project and solution files
!*.vcxproj
!*.vcxproj.filters
!*.sln

254
build.vc10/daemon.vcxproj Normal file
View file

@ -0,0 +1,254 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D0D81A98-2946-4A16-A4A1-800387C3F3D1}</ProjectGuid>
<RootNamespace>daemon</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nfsd</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nfsd</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nfsd</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nfsd</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;..\xdr;..\dll;..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;..\xdr;..\dll;..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;..\xdr;..\dll;..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;..\xdr;..\dll;..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\daemon\callback_xdr.c" />
<ClCompile Include="..\daemon\callback_server.c" />
<ClCompile Include="..\daemon\daemon_debug.c" />
<ClCompile Include="..\daemon\getattr.c" />
<ClCompile Include="..\daemon\lock.c" />
<ClCompile Include="..\daemon\lookup.c" />
<ClCompile Include="..\daemon\mount.c" />
<ClCompile Include="..\daemon\namespace.c" />
<ClCompile Include="..\daemon\name_cache.c" />
<ClCompile Include="..\daemon\nfs41_client.c" />
<ClCompile Include="..\daemon\nfs41_compound.c" />
<ClCompile Include="..\daemon\nfs41_daemon.c" />
<ClCompile Include="..\daemon\nfs41_ops.c" />
<ClCompile Include="..\daemon\nfs41_rpc.c" />
<ClCompile Include="..\daemon\nfs41_server.c" />
<ClCompile Include="..\daemon\nfs41_session.c" />
<ClCompile Include="..\daemon\nfs41_superblock.c" />
<ClCompile Include="..\daemon\nfs41_xdr.c" />
<ClCompile Include="..\daemon\open.c" />
<ClCompile Include="..\daemon\pnfs_debug.c" />
<ClCompile Include="..\daemon\pnfs_device.c" />
<ClCompile Include="..\daemon\pnfs_io.c" />
<ClCompile Include="..\daemon\pnfs_layout.c" />
<ClCompile Include="..\daemon\rbtree.c" />
<ClCompile Include="..\daemon\readdir.c" />
<ClCompile Include="..\daemon\readwrite.c" />
<ClCompile Include="..\daemon\setattr.c" />
<ClCompile Include="..\daemon\upcall.c" />
<ClCompile Include="..\daemon\util.c" />
<ClCompile Include="..\daemon\volume.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\daemon\daemon_debug.h" />
<ClInclude Include="..\daemon\from_kernel.h" />
<ClInclude Include="..\daemon\list.h" />
<ClInclude Include="..\daemon\name_cache.h" />
<ClInclude Include="..\daemon\nfs41.h" />
<ClInclude Include="..\daemon\nfs41_callback.h" />
<ClInclude Include="..\daemon\nfs41_compound.h" />
<ClInclude Include="..\daemon\nfs41_const.h" />
<ClInclude Include="..\daemon\nfs41_ops.h" />
<ClInclude Include="..\daemon\nfs41_types.h" />
<ClInclude Include="..\daemon\nfs41_xdr.h" />
<ClInclude Include="..\daemon\pnfs.h" />
<ClInclude Include="..\daemon\rbtree.h" />
<ClInclude Include="..\daemon\upcall.h" />
<ClInclude Include="..\daemon\util.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\daemon\sources" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libtirpc.vcxproj">
<Project>{2d918a9b-de52-470a-93d5-78ea2c8113a1}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{b39281cd-23c6-401e-844b-3d6c763da90b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\daemon\daemon_debug.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\getattr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\lock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\mount.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_client.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_compound.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_daemon.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_ops.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_rpc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_server.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_session.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_superblock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\nfs41_xdr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\open.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\pnfs_debug.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\pnfs_device.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\pnfs_layout.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\readdir.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\readwrite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\setattr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\upcall.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\util.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\pnfs_io.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\lookup.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\rbtree.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\name_cache.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\namespace.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\volume.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\callback_server.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\daemon\callback_xdr.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\daemon\daemon_debug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\from_kernel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_compound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_const.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_ops.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_xdr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\pnfs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\upcall.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\list.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\rbtree.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\name_cache.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\daemon\nfs41_callback.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\daemon\sources">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

208
build.vc10/dll.vcxproj Normal file
View file

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}</ProjectGuid>
<RootNamespace>dll</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<OutputFile>$(OutDir)nfs41_np.dll</OutputFile>
<ModuleDefinitionFile>..\dll\nfs41_np.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<BaseAddress>0x1010000</BaseAddress>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<OutputFile>$(OutDir)nfs41_np.dll</OutputFile>
<ModuleDefinitionFile>..\dll\nfs41_np.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<BaseAddress>0x1010000</BaseAddress>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<OutputFile>$(OutDir)nfs41_np.dll</OutputFile>
<ModuleDefinitionFile>..\dll\nfs41_np.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<BaseAddress>0x1010000</BaseAddress>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<OutputFile>$(OutDir)nfs41_np.dll</OutputFile>
<ModuleDefinitionFile>..\dll\nfs41_np.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<BaseAddress>0x1010000</BaseAddress>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\dll\dllmain.c" />
<ClCompile Include="..\dll\nfs41_np.c" />
<ClCompile Include="..\dll\options.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\dll\nfs41_np.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\dll\nfs41_np.def" />
<None Include="..\dll\sources" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\dll\dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\dll\nfs41_np.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\dll\options.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\dll\nfs41_np.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\dll\nfs41_np.def">
<Filter>Resource Files</Filter>
</None>
<None Include="..\dll\sources">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<WDKPATH>C:\WinDDK\7600.16385.0</WDKPATH>
</PropertyGroup>
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<_PropertySheetDisplayName>ddk_env</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<BuildMacro Include="WDKPATH">
<Value>$(WDKPATH)</Value>
</BuildMacro>
</ItemGroup>
</Project>

308
build.vc10/libtirpc.vcxproj Normal file
View file

@ -0,0 +1,308 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2D918A9B-DE52-470A-93D5-78EA2C8113A1}</ProjectGuid>
<RootNamespace>libtirpc</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>INET6;FD_SETSIZE=128;PORTMAP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>..\libtirpc\libtirpc\libtirpc.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>INET6;FD_SETSIZE=128;PORTMAP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>..\libtirpc\libtirpc\libtirpc.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EntryPointSymbol>
</EntryPointSymbol>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>INET6;FD_SETSIZE=128;PORTMAP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>..\libtirpc\libtirpc\libtirpc.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\libtirpc\tirpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>INET6;FD_SETSIZE=128;PORTMAP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>..\libtirpc\libtirpc\libtirpc.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<EntryPointSymbol>
</EntryPointSymbol>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\libtirpc\src\asprintf.c" />
<ClCompile Include="..\libtirpc\src\auth_none.c" />
<ClCompile Include="..\libtirpc\src\auth_time.c" />
<ClCompile Include="..\libtirpc\src\auth_unix.c" />
<ClCompile Include="..\libtirpc\src\authunix_prot.c" />
<ClCompile Include="..\libtirpc\src\bindresvport.c" />
<ClCompile Include="..\libtirpc\src\clnt_bcast.c" />
<ClCompile Include="..\libtirpc\src\clnt_dg.c" />
<ClCompile Include="..\libtirpc\src\clnt_generic.c" />
<ClCompile Include="..\libtirpc\src\clnt_perror.c" />
<ClCompile Include="..\libtirpc\src\clnt_raw.c" />
<ClCompile Include="..\libtirpc\src\clnt_simple.c" />
<ClCompile Include="..\libtirpc\src\clnt_vc.c" />
<ClCompile Include="..\libtirpc\src\des_soft.c" />
<ClCompile Include="..\libtirpc\src\epoll_sub.c" />
<ClCompile Include="..\libtirpc\src\getnetconfig.c" />
<ClCompile Include="..\libtirpc\src\getnetpath.c" />
<ClCompile Include="..\libtirpc\src\getpeereid.c" />
<ClCompile Include="..\libtirpc\src\getpublickey.c" />
<ClCompile Include="..\libtirpc\src\getrpcent.c" />
<ClCompile Include="..\libtirpc\src\getrpcport.c" />
<ClCompile Include="..\libtirpc\src\gettimeofday.c" />
<ClCompile Include="..\libtirpc\src\key_call.c" />
<ClCompile Include="..\libtirpc\src\key_prot_xdr.c" />
<ClCompile Include="..\libtirpc\src\mt_misc.c" />
<ClCompile Include="..\libtirpc\src\netname.c" />
<ClCompile Include="..\libtirpc\src\netnamer.c" />
<ClCompile Include="..\libtirpc\src\pmap_clnt.c" />
<ClCompile Include="..\libtirpc\src\pmap_getmaps.c" />
<ClCompile Include="..\libtirpc\src\pmap_getport.c" />
<ClCompile Include="..\libtirpc\src\pmap_prot.c" />
<ClCompile Include="..\libtirpc\src\pmap_prot2.c" />
<ClCompile Include="..\libtirpc\src\pmap_rmt.c" />
<ClCompile Include="..\libtirpc\src\rpc_callmsg.c" />
<ClCompile Include="..\libtirpc\src\rpc_commondata.c" />
<ClCompile Include="..\libtirpc\src\rpc_dtablesize.c" />
<ClCompile Include="..\libtirpc\src\rpc_generic.c" />
<ClCompile Include="..\libtirpc\src\rpc_prot.c" />
<ClCompile Include="..\libtirpc\src\rpc_soc.c" />
<ClCompile Include="..\libtirpc\src\rpcb_clnt.c" />
<ClCompile Include="..\libtirpc\src\rpcb_prot.c" />
<ClCompile Include="..\libtirpc\src\rpcb_st_xdr.c" />
<ClCompile Include="..\libtirpc\src\rpcdname.c" />
<ClCompile Include="..\libtirpc\src\rtime.c" />
<ClCompile Include="..\libtirpc\src\svc.c" />
<ClCompile Include="..\libtirpc\src\svc_auth.c" />
<ClCompile Include="..\libtirpc\src\svc_auth_none.c" />
<ClCompile Include="..\libtirpc\src\svc_auth_unix.c" />
<ClCompile Include="..\libtirpc\src\svc_dg.c" />
<ClCompile Include="..\libtirpc\src\svc_generic.c" />
<ClCompile Include="..\libtirpc\src\svc_raw.c" />
<ClCompile Include="..\libtirpc\src\svc_run.c" />
<ClCompile Include="..\libtirpc\src\svc_simple.c" />
<ClCompile Include="..\libtirpc\src\svc_vc.c" />
<ClCompile Include="..\libtirpc\src\winstubs.c" />
<ClCompile Include="..\libtirpc\src\wintirpc.c" />
<ClCompile Include="..\libtirpc\src\xdr.c" />
<ClCompile Include="..\libtirpc\src\xdr_array.c" />
<ClCompile Include="..\libtirpc\src\xdr_float.c" />
<ClCompile Include="..\libtirpc\src\xdr_mem.c" />
<ClCompile Include="..\libtirpc\src\xdr_rec.c" />
<ClCompile Include="..\libtirpc\src\xdr_reference.c" />
<ClCompile Include="..\libtirpc\src\xdr_sizeof.c" />
<ClCompile Include="..\libtirpc\src\xdr_stdio.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\libtirpc\src\rpc_com.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\auth.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_des.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_gss.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_kerb.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_unix.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt_soc.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt_stat.h" />
<ClInclude Include="..\libtirpc\tirpc\rpcsvc\crypt.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\des.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\des_crypt.h" />
<ClInclude Include="..\libtirpc\tirpc\misc\event.h" />
<ClInclude Include="..\libtirpc\tirpc\fpmath.h" />
<ClInclude Include="..\libtirpc\tirpc\getpeereid.h" />
<ClInclude Include="..\libtirpc\tirpc\libc_private.h" />
<ClInclude Include="..\libtirpc\tirpc\namespace.h" />
<ClInclude Include="..\libtirpc\tirpc\netconfig.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\nettype.h" />
<ClInclude Include="..\libtirpc\tirpc\rpcsvc\nis.h" />
<ClInclude Include="..\libtirpc\tirpc\nss_tls.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_clnt.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_prot.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_rmt.h" />
<ClInclude Include="..\libtirpc\tirpc\sys\queue.h" />
<ClInclude Include="..\libtirpc\tirpc\misc\queue.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\raw.h" />
<ClInclude Include="..\libtirpc\tirpc\reentrant.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc_com.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc_msg.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcb_clnt.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcb_prot.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcent.h" />
<ClInclude Include="..\libtirpc\tirpc\misc\socket.h" />
<ClInclude Include="..\libtirpc\tirpc\spinlock.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\svc.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_auth.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_dg.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_soc.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\types.h" />
<ClInclude Include="..\libtirpc\tirpc\un-namespace.h" />
<ClInclude Include="..\libtirpc\tirpc\wintirpc.h" />
<ClInclude Include="..\libtirpc\tirpc\rpc\xdr.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\libtirpc\libtirpc\libtirpc.rc" />
</ItemGroup>
<ItemGroup>
<None Include="..\libtirpc\libtirpc\libtirpc.def" />
<None Include="..\libtirpc\src\sources" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,358 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\libtirpc\src\asprintf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\auth_none.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\auth_time.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\auth_unix.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\authunix_prot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\bindresvport.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_bcast.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_dg.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_generic.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_perror.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_raw.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_simple.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\clnt_vc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\des_soft.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\epoll_sub.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getnetconfig.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getnetpath.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getpeereid.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getpublickey.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getrpcent.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\getrpcport.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\gettimeofday.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\key_call.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\key_prot_xdr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\mt_misc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\netname.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\netnamer.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_clnt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_getmaps.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_getport.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_prot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_prot2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\pmap_rmt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_callmsg.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_commondata.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_dtablesize.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_generic.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_prot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpc_soc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpcb_clnt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpcb_prot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpcb_st_xdr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rpcdname.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\rtime.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_auth.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_auth_none.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_auth_unix.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_dg.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_generic.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_raw.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_run.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_simple.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\svc_vc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\winstubs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\wintirpc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_array.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_float.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_mem.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_rec.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_reference.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_sizeof.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libtirpc\src\xdr_stdio.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\libtirpc\src\rpc_com.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\auth.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_des.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_gss.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_kerb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\auth_unix.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt_soc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\clnt_stat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpcsvc\crypt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\des.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\des_crypt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\misc\event.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\fpmath.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\getpeereid.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\libc_private.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\namespace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\netconfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\nettype.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpcsvc\nis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\nss_tls.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_clnt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_prot.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\pmap_rmt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\sys\queue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\misc\queue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\raw.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\reentrant.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc_com.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpc_msg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcb_clnt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcb_prot.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\rpcent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\misc\socket.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\spinlock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\svc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_auth.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_dg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\svc_soc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\un-namespace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\wintirpc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libtirpc\tirpc\rpc\xdr.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\libtirpc\libtirpc\libtirpc.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\libtirpc\src\sources">
<Filter>Resource Files</Filter>
</None>
<None Include="..\libtirpc\libtirpc\libtirpc.def">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

187
build.vc10/mount.vcxproj Normal file
View file

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5AEA3497-6852-471B-A252-ADA60B22A342}</ProjectGuid>
<RootNamespace>mount</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\mount\enum.c" />
<ClCompile Include="..\mount\mount.c" />
<ClCompile Include="..\mount\options.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\mount\options.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\mount\sources" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\mount\enum.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\mount\mount.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\mount\options.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\mount\options.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\mount\sources">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,76 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "daemon", "daemon.vcxproj", "{D0D81A98-2946-4A16-A4A1-800387C3F3D1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcxproj", "{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs41_driver", "nfs41_driver.vcxproj", "{B64D3074-519F-476A-A3AA-DAD6554CBB68}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mount", "mount.vcxproj", "{5AEA3497-6852-471B-A252-ADA60B22A342}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtirpc", "libtirpc.vcxproj", "{2D918A9B-DE52-470A-93D5-78EA2C8113A1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs_install", "nfs_install.vcxproj", "{A453DC17-BE6B-4271-A020-66E054AB5908}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|Win32.Build.0 = Debug|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|x64.ActiveCfg = Debug|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|x64.Build.0 = Debug|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|Win32.ActiveCfg = Release|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|Win32.Build.0 = Release|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|x64.ActiveCfg = Release|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|x64.Build.0 = Release|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|Win32.ActiveCfg = Debug|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|Win32.Build.0 = Debug|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|x64.ActiveCfg = Debug|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|x64.Build.0 = Debug|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|Win32.ActiveCfg = Release|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|Win32.Build.0 = Release|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|x64.ActiveCfg = Release|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|x64.Build.0 = Release|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|Win32.ActiveCfg = Debug|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|Win32.Build.0 = Debug|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|x64.ActiveCfg = Debug|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|x64.Build.0 = Debug|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|Win32.ActiveCfg = Release|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|Win32.Build.0 = Release|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|x64.ActiveCfg = Release|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|x64.Build.0 = Release|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|Win32.ActiveCfg = Debug|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|Win32.Build.0 = Debug|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|x64.ActiveCfg = Debug|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|x64.Build.0 = Debug|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|Win32.ActiveCfg = Release|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|Win32.Build.0 = Release|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|x64.ActiveCfg = Release|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|x64.Build.0 = Release|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|Win32.ActiveCfg = Debug|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|Win32.Build.0 = Debug|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|x64.ActiveCfg = Debug|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|x64.Build.0 = Debug|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|Win32.ActiveCfg = Release|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|Win32.Build.0 = Release|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|x64.ActiveCfg = Release|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|x64.Build.0 = Release|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|Win32.ActiveCfg = Debug|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|Win32.Build.0 = Debug|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|x64.ActiveCfg = Debug|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|x64.Build.0 = Debug|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|Win32.ActiveCfg = Release|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|Win32.Build.0 = Release|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|x64.ActiveCfg = Release|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B64D3074-519F-476A-A3AA-DAD6554CBB68}</ProjectGuid>
<Keyword>MakeFileProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="env.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\projects\ms-nfs41-client\sys\objchk_wlh_x86\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\projects\ms-nfs41-client\sys\objchk_wlh_x86\</IntDir>
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x86 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_x86
call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x86 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_x86</NMakeCleanCommandLine>
<NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\projects\ms-nfs41-client\sys\objchk_wlh_x86\i386\nfs41_driver.sys</NMakeOutput>
<NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_CONSOLE;_X86_;_DDK_;_DEBUG;DBG=1;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
<NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
<NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64\</IntDir>
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64
call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64</NMakeCleanCommandLine>
<NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64\amd64\nfs41_driver.sys</NMakeOutput>
<NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN32;_CONSOLE;_AMD64_;_DDK_;_DEBUG;DBG=1;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
<NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
<NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\projects\ms-nfs41-client\sys\objfre_wlh_x86\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\projects\ms-nfs41-client\sys\objfre_wlh_x86\</IntDir>
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x86 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_x86
call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x86 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_x86</NMakeCleanCommandLine>
<NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\projects\ms-nfs41-client\sys\objfre_wlh_x86\i386\nfs41_driver.sys</NMakeOutput>
<NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;_CONSOLE;_X86_;_DDK_;_NDEBUG;DBG=0;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
<NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
<NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64\</IntDir>
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeBuildCommandLine>
<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64
call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 wlh
cd /d C:\projects\ms-nfs41-client\sys
build</NMakeReBuildCommandLine>
<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64</NMakeCleanCommandLine>
<NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64\amd64\nfs41_driver.sys</NMakeOutput>
<NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN32;_CONSOLE;_AMD64_;_DDK_;_NDEBUG;DBG=0;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
<NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
<NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
</PropertyGroup>
<ItemDefinitionGroup>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\sys\nfs41_debug.c" />
<ClCompile Include="..\sys\nfs41_driver.c" />
<ClCompile Include="..\sys\wmlkm.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\sys\makefile" />
<None Include="..\sys\nfs41_driver.ini" />
<None Include="..\sys\sources" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\sys\nfs41_driver.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sys\nfs41_debug.h" />
<ClInclude Include="..\sys\nfs41_driver.h" />
<ClInclude Include="..\sys\wmlkm.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source files">
<UniqueIdentifier>{5cb3db05-7cb6-47df-835b-1f900bc6588b}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Resource files">
<UniqueIdentifier>{3eaffb55-1a2a-45b8-9ab0-1ae04813d050}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header files">
<UniqueIdentifier>{b673e717-daca-4c21-8935-bee66da864fb}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\sys\nfs41_debug.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\sys\nfs41_driver.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\sys\wmlkm.c">
<Filter>Source files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\sys\makefile">
<Filter>Resource files</Filter>
</None>
<None Include="..\sys\nfs41_driver.ini">
<Filter>Resource files</Filter>
</None>
<None Include="..\sys\sources">
<Filter>Resource files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\sys\nfs41_driver.rc">
<Filter>Resource files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sys\nfs41_debug.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\sys\nfs41_driver.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\sys\wmlkm.h">
<Filter>Header files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A453DC17-BE6B-4271-A020-66E054AB5908}</ProjectGuid>
<RootNamespace>nfs_install</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214 %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\sys;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\install\nfs_install.c" />
<ClCompile Include="..\install\nfsreginst.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\install\nfsreginst.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\install\sources" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\install\nfs_install.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\install\nfsreginst.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\install\nfsreginst.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\install\sources">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

6
build.vc9/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
# exclude all build files by default
*
# allow visual studio project and solution files
!*.vcproj
!*.sln

536
build.vc9/daemon.vcproj Normal file
View file

@ -0,0 +1,536 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="daemon"
ProjectGUID="{D0D81A98-2946-4A16-A4A1-800387C3F3D1}"
RootNamespace="daemon"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys;..\xdr;..\dll;..\libtirpc\tirpc"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib iphlpapi.lib"
OutputFile="$(OutDir)\nfsd.exe"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys;..\xdr;..\dll;..\libtirpc\tirpc"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib iphlpapi.lib"
OutputFile="$(OutDir)\nfsd.exe"
GenerateDebugInformation="true"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys;..\xdr;..\dll;..\libtirpc\tirpc"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib iphlpapi.lib"
OutputFile="$(OutDir)\nfsd.exe"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys;..\xdr;..\dll;..\libtirpc\tirpc"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib iphlpapi.lib"
OutputFile="$(OutDir)\nfsd.exe"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\daemon\callback_server.c"
>
</File>
<File
RelativePath="..\daemon\callback_xdr.c"
>
</File>
<File
RelativePath="..\daemon\daemon_debug.c"
>
</File>
<File
RelativePath="..\daemon\getattr.c"
>
</File>
<File
RelativePath="..\daemon\lock.c"
>
</File>
<File
RelativePath="..\daemon\lookup.c"
>
</File>
<File
RelativePath="..\daemon\mount.c"
>
</File>
<File
RelativePath="..\daemon\name_cache.c"
>
</File>
<File
RelativePath="..\daemon\namespace.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_client.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_compound.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_daemon.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_ops.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_rpc.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_server.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_session.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_superblock.c"
>
</File>
<File
RelativePath="..\daemon\nfs41_xdr.c"
>
</File>
<File
RelativePath="..\daemon\open.c"
>
</File>
<File
RelativePath="..\daemon\pnfs_debug.c"
>
</File>
<File
RelativePath="..\daemon\pnfs_device.c"
>
</File>
<File
RelativePath="..\daemon\pnfs_io.c"
>
</File>
<File
RelativePath="..\daemon\pnfs_layout.c"
>
</File>
<File
RelativePath="..\daemon\rbtree.c"
>
</File>
<File
RelativePath="..\daemon\readdir.c"
>
</File>
<File
RelativePath="..\daemon\readwrite.c"
>
</File>
<File
RelativePath="..\daemon\setattr.c"
>
</File>
<File
RelativePath="..\daemon\upcall.c"
>
</File>
<File
RelativePath="..\daemon\util.c"
>
</File>
<File
RelativePath="..\daemon\volume.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\daemon\daemon_debug.h"
>
</File>
<File
RelativePath="..\daemon\from_kernel.h"
>
</File>
<File
RelativePath="..\daemon\list.h"
>
</File>
<File
RelativePath="..\daemon\name_cache.h"
>
</File>
<File
RelativePath="..\daemon\nfs41.h"
>
</File>
<File
RelativePath="..\daemon\nfs41_compound.h"
>
</File>
<File
RelativePath="..\daemon\nfs41_const.h"
>
</File>
<File
RelativePath="..\daemon\nfs41_ops.h"
>
</File>
<File
RelativePath="..\daemon\nfs41_types.h"
>
</File>
<File
RelativePath="..\daemon\nfs41_xdr.h"
>
</File>
<File
RelativePath="..\daemon\pnfs.h"
>
</File>
<File
RelativePath="..\daemon\rbtree.h"
>
</File>
<File
RelativePath="..\daemon\upcall.h"
>
</File>
<File
RelativePath="..\daemon\util.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
>
<File
RelativePath="..\daemon\sources"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

386
build.vc9/dll.vcproj Normal file
View file

@ -0,0 +1,386 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="dll"
ProjectGUID="{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}"
RootNamespace="dll"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
PreprocessorDefinitions="UNICODE;_UNICODE"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\nfs41_np.dll"
ModuleDefinitionFile="..\dll\nfs41_np.def"
GenerateDebugInformation="true"
BaseAddress="0x1010000"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
PreprocessorDefinitions="UNICODE;_UNICODE"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\nfs41_np.dll"
ModuleDefinitionFile="..\dll\nfs41_np.def"
GenerateDebugInformation="true"
BaseAddress="0x1010000"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
PreprocessorDefinitions="UNICODE;_UNICODE"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\nfs41_np.dll"
ModuleDefinitionFile="..\dll\nfs41_np.def"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
BaseAddress="0x1010000"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
InheritedPropertySheets=".\env.vsprops"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
PreprocessorDefinitions="UNICODE;_UNICODE"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
RuntimeTypeInfo="false"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\nfs41_np.dll"
ModuleDefinitionFile="..\dll\nfs41_np.def"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
BaseAddress="0x1010000"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\dll\dllmain.c"
>
</File>
<File
RelativePath="..\dll\nfs41_np.c"
>
</File>
<File
RelativePath="..\dll\options.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\dll\nfs41_np.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\dll\nfs41_np.def"
>
</File>
<File
RelativePath="..\dll\sources"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="ddk_env"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
/>
<Tool
Name="VCNMakeTool"
BuildCommandLine=""
ReBuildCommandLine=""
CleanCommandLine=""
Output=""
PreprocessorDefinitions=""
IncludeSearchPath="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
<UserMacro
Name="WDKPATH"
Value="C:\WinDDK\7600.16385.0"
/>
</VisualStudioPropertySheet>

793
build.vc9/libtirpc.vcproj Normal file
View file

@ -0,0 +1,793 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libtirpc"
ProjectGUID="{2D918A9B-DE52-470A-93D5-78EA2C8113A1}"
RootNamespace="libtirpc"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\libtirpc\tirpc"
PreprocessorDefinitions="INET6;FD_SETSIZE=128;PORTMAP"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
LinkIncremental="1"
ModuleDefinitionFile="..\libtirpc\libtirpc\libtirpc.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\libtirpc\tirpc"
PreprocessorDefinitions="INET6;FD_SETSIZE=128;PORTMAP"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
LinkIncremental="1"
ModuleDefinitionFile="..\libtirpc\libtirpc\libtirpc.def"
GenerateDebugInformation="true"
SubSystem="2"
EntryPointSymbol=""
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\libtirpc\tirpc"
PreprocessorDefinitions="INET6;FD_SETSIZE=128;PORTMAP"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
LinkIncremental="1"
ModuleDefinitionFile="..\libtirpc\libtirpc\libtirpc.def"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\libtirpc\tirpc"
PreprocessorDefinitions="INET6;FD_SETSIZE=128;PORTMAP"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
LinkIncremental="1"
ModuleDefinitionFile="..\libtirpc\libtirpc\libtirpc.def"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
EntryPointSymbol=""
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\libtirpc\src\asprintf.c"
>
</File>
<File
RelativePath="..\libtirpc\src\auth_none.c"
>
</File>
<File
RelativePath="..\libtirpc\src\auth_time.c"
>
</File>
<File
RelativePath="..\libtirpc\src\auth_unix.c"
>
</File>
<File
RelativePath="..\libtirpc\src\authunix_prot.c"
>
</File>
<File
RelativePath="..\libtirpc\src\bindresvport.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_bcast.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_dg.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_generic.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_perror.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_raw.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_simple.c"
>
</File>
<File
RelativePath="..\libtirpc\src\clnt_vc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\des_soft.c"
>
</File>
<File
RelativePath="..\libtirpc\src\epoll_sub.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getnetconfig.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getnetpath.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getpeereid.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getpublickey.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getrpcent.c"
>
</File>
<File
RelativePath="..\libtirpc\src\getrpcport.c"
>
</File>
<File
RelativePath="..\libtirpc\src\gettimeofday.c"
>
</File>
<File
RelativePath="..\libtirpc\src\key_call.c"
>
</File>
<File
RelativePath="..\libtirpc\src\key_prot_xdr.c"
>
</File>
<File
RelativePath="..\libtirpc\src\mt_misc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\netname.c"
>
</File>
<File
RelativePath="..\libtirpc\src\netnamer.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_clnt.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_getmaps.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_getport.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_prot.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_prot2.c"
>
</File>
<File
RelativePath="..\libtirpc\src\pmap_rmt.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_callmsg.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_com.h"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_commondata.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_dtablesize.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_generic.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_prot.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpc_soc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpcb_clnt.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpcb_prot.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpcb_st_xdr.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rpcdname.c"
>
</File>
<File
RelativePath="..\libtirpc\src\rtime.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_auth.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_auth_none.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_auth_unix.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_dg.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_generic.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_raw.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_run.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_simple.c"
>
</File>
<File
RelativePath="..\libtirpc\src\svc_vc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\winstubs.c"
>
</File>
<File
RelativePath="..\libtirpc\src\wintirpc.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_array.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_float.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_mem.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_rec.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_reference.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_sizeof.c"
>
</File>
<File
RelativePath="..\libtirpc\src\xdr_stdio.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\libtirpc\tirpc\rpc\auth.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\auth_des.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\auth_gss.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\auth_kerb.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\auth_unix.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\clnt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\clnt_soc.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\clnt_stat.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpcsvc\crypt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\des.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\des_crypt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\misc\event.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\fpmath.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\getpeereid.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\libc_private.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\namespace.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\netconfig.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\nettype.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpcsvc\nis.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\nss_tls.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\pmap_clnt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\pmap_prot.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\pmap_rmt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\sys\queue.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\misc\queue.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\raw.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\reentrant.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpc.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpc_com.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpc_msg.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpcb_clnt.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpcb_prot.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\rpcent.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\misc\socket.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\spinlock.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\svc.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\svc_auth.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\svc_dg.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\svc_soc.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\types.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\un-namespace.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\wintirpc.h"
>
</File>
<File
RelativePath="..\libtirpc\tirpc\rpc\xdr.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\libtirpc\libtirpc\libtirpc.rc"
>
</File>
<File
RelativePath="..\libtirpc\src\sources"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

362
build.vc9/mount.vcproj Normal file
View file

@ -0,0 +1,362 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mount"
ProjectGUID="{5AEA3497-6852-471B-A252-ADA60B22A342}"
RootNamespace="mount"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="4"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="mpr.lib"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="mpr.lib"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="mpr.lib"
GenerateDebugInformation="true"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="4"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="mpr.lib"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\mount\enum.c"
>
</File>
<File
RelativePath="..\mount\mount.c"
>
</File>
<File
RelativePath="..\mount\options.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\mount\options.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\mount\sources"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,79 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "daemon", "daemon.vcproj", "{D0D81A98-2946-4A16-A4A1-800387C3F3D1}"
ProjectSection(ProjectDependencies) = postProject
{2D918A9B-DE52-470A-93D5-78EA2C8113A1} = {2D918A9B-DE52-470A-93D5-78EA2C8113A1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcproj", "{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs41_driver", "nfs41_driver.vcproj", "{B64D3074-519F-476A-A3AA-DAD6554CBB68}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mount", "mount.vcproj", "{5AEA3497-6852-471B-A252-ADA60B22A342}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtirpc", "libtirpc.vcproj", "{2D918A9B-DE52-470A-93D5-78EA2C8113A1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs_install", "nfs_install.vcproj", "{A453DC17-BE6B-4271-A020-66E054AB5908}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|Win32.Build.0 = Debug|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|x64.ActiveCfg = Debug|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Debug|x64.Build.0 = Debug|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|Win32.ActiveCfg = Release|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|Win32.Build.0 = Release|Win32
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|x64.ActiveCfg = Release|x64
{D0D81A98-2946-4A16-A4A1-800387C3F3D1}.Release|x64.Build.0 = Release|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|Win32.ActiveCfg = Debug|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|Win32.Build.0 = Debug|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|x64.ActiveCfg = Debug|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Debug|x64.Build.0 = Debug|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|Win32.ActiveCfg = Release|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|Win32.Build.0 = Release|Win32
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|x64.ActiveCfg = Release|x64
{372D9D02-CDC5-43AE-BB0A-FB57CEFC639C}.Release|x64.Build.0 = Release|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|Win32.ActiveCfg = Debug|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|Win32.Build.0 = Debug|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|x64.ActiveCfg = Debug|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Debug|x64.Build.0 = Debug|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|Win32.ActiveCfg = Release|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|Win32.Build.0 = Release|Win32
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|x64.ActiveCfg = Release|x64
{B64D3074-519F-476A-A3AA-DAD6554CBB68}.Release|x64.Build.0 = Release|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|Win32.ActiveCfg = Debug|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|Win32.Build.0 = Debug|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|x64.ActiveCfg = Debug|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Debug|x64.Build.0 = Debug|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|Win32.ActiveCfg = Release|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|Win32.Build.0 = Release|Win32
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|x64.ActiveCfg = Release|x64
{5AEA3497-6852-471B-A252-ADA60B22A342}.Release|x64.Build.0 = Release|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|Win32.ActiveCfg = Debug|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|Win32.Build.0 = Debug|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|x64.ActiveCfg = Debug|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Debug|x64.Build.0 = Debug|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|Win32.ActiveCfg = Release|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|Win32.Build.0 = Release|Win32
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|x64.ActiveCfg = Release|x64
{2D918A9B-DE52-470A-93D5-78EA2C8113A1}.Release|x64.Build.0 = Release|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|Win32.ActiveCfg = Debug|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|Win32.Build.0 = Debug|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|x64.ActiveCfg = Debug|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Debug|x64.Build.0 = Debug|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|Win32.ActiveCfg = Release|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|Win32.Build.0 = Release|Win32
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|x64.ActiveCfg = Release|x64
{A453DC17-BE6B-4271-A020-66E054AB5908}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="nfs41_driver"
ProjectGUID="{B64D3074-519F-476A-A3AA-DAD6554CBB68}"
Keyword="MakeFileProj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="C:\projects\ms-nfs41-client\sys\objchk_wlh_x86"
IntermediateDirectory="C:\projects\ms-nfs41-client\sys\objchk_wlh_x86"
ConfigurationType="0"
InheritedPropertySheets=".\env.vsprops"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x86 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
ReBuildCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_x86&#x0D;&#x0A;call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x86 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
CleanCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_x86"
Output="C:\projects\ms-nfs41-client\sys\objchk_wlh_x86\i386\nfs41_driver.sys"
PreprocessorDefinitions="WIN32;_CONSOLE;_X86_;_DDK_;_DEBUG;DBG=1"
IncludeSearchPath="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64"
IntermediateDirectory="C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64"
ConfigurationType="0"
InheritedPropertySheets=".\env.vsprops"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
ReBuildCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64&#x0D;&#x0A;call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
CleanCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64"
Output="C:\projects\ms-nfs41-client\sys\objchk_wlh_amd64\amd64\nfs41_driver.sys"
PreprocessorDefinitions="WIN32;_CONSOLE;_AMD64_;_DDK_;_DEBUG;DBG=1"
IncludeSearchPath="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="C:\projects\ms-nfs41-client\sys\objfre_wlh_x86"
IntermediateDirectory="C:\projects\ms-nfs41-client\sys\objfre_wlh_x86"
ConfigurationType="0"
InheritedPropertySheets=".\env.vsprops"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x86 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
ReBuildCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_x86&#x0D;&#x0A;call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x86 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
CleanCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_x86"
Output="C:\projects\ms-nfs41-client\sys\objfre_wlh_x86\i386\nfs41_driver.sys"
PreprocessorDefinitions="WIN32;_CONSOLE;_X86_;_DDK_;_NDEBUG;DBG=0"
IncludeSearchPath="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64"
IntermediateDirectory="C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64"
ConfigurationType="0"
InheritedPropertySheets=".\env.vsprops"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
ReBuildCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64&#x0D;&#x0A;call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 wlh&#x0D;&#x0A;cd /d C:\projects\ms-nfs41-client\sys&#x0D;&#x0A;build"
CleanCommandLine="rmdir /s /q C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64"
Output="C:\projects\ms-nfs41-client\sys\objfre_wlh_amd64\amd64\nfs41_driver.sys"
PreprocessorDefinitions="WIN32;_CONSOLE;_AMD64_;_DDK_;_NDEBUG;DBG=0"
IncludeSearchPath="$(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt"
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
>
<File
RelativePath="..\sys\nfs41_debug.c"
>
</File>
<File
RelativePath="..\sys\nfs41_driver.c"
>
</File>
<File
RelativePath="..\sys\wmlkm.c"
>
</File>
</Filter>
<Filter
Name="Resource files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
>
<File
RelativePath="..\sys\makefile"
>
</File>
<File
RelativePath="..\sys\nfs41_driver.ini"
>
</File>
<File
RelativePath="..\sys\nfs41_driver.rc"
>
</File>
<File
RelativePath="..\sys\sources"
>
</File>
</Filter>
<Filter
Name="Header files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
>
<File
RelativePath="..\sys\nfs41_debug.h"
>
</File>
<File
RelativePath="..\sys\nfs41_driver.h"
>
</File>
<File
RelativePath="..\sys\wmlkm.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,354 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="nfs_install"
ProjectGUID="{A453DC17-BE6B-4271-A020-66E054AB5908}"
RootNamespace="nfs_install"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214"
Optimization="0"
AdditionalIncludeDirectories="..\sys"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
GenerateDebugInformation="true"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\sys"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\install\nfs_install.c"
>
</File>
<File
RelativePath="..\install\nfsreginst.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\install\nfsreginst.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\install\sources"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

381
daemon/callback_server.c Normal file
View file

@ -0,0 +1,381 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include "nfs41.h"
#include "nfs41_ops.h"
#include "nfs41_callback.h"
#include "daemon_debug.h"
#define CBSLVL 2 /* dprintf level for callback server logging */
static const char g_server_tag[] = "ms-nfs41-callback";
/* OP_CB_LAYOUTRECALL */
static enum_t handle_cb_layoutrecall(
IN nfs41_rpc_clnt *rpc_clnt,
IN struct cb_layoutrecall_args *args,
OUT struct cb_layoutrecall_res *res)
{
enum pnfs_status status;
/* forgetful model for layout recalls; return NOMATCHING_LAYOUT
* and flag the layout(s) to prevent further use */
res->status = NFS4ERR_NOMATCHING_LAYOUT;
dprintf(CBSLVL, " OP_CB_LAYOUTRECALL { %s, %s, recall %u } %s\n",
pnfs_layout_type_string(args->type),
pnfs_iomode_string(args->iomode), args->recall.type,
nfs_error_string(res->status));
status = pnfs_file_layout_recall(rpc_clnt->client->layouts, args);
if (status)
eprintf("pnfs_file_layout_recall() failed with %s\n",
pnfs_error_string(status));
return res->status;
}
/* OP_CB_RECALL_SLOT */
static enum_t handle_cb_recall_slot(
IN struct cb_recall_slot_args *args,
OUT struct cb_recall_slot_res *res)
{
res->status = NFS4_OK;
dprintf(CBSLVL, " OP_CB_RECALL_SLOT { %u } %s\n",
args->target_highest_slotid, nfs_error_string(res->status));
return res->status;
}
/* OP_CB_SEQUENCE */
static enum_t handle_cb_sequence(
IN nfs41_rpc_clnt *rpc_clnt,
IN struct cb_sequence_args *args,
OUT struct cb_sequence_res *res)
{
nfs41_cb_session *cb_session = &rpc_clnt->client->session->cb_session;
uint32_t status = NFS4_OK;
res->status = NFS4_OK;
if (!cb_session->cb_is_valid_state) {
memcpy(cb_session->cb_sessionid, args->sessionid, NFS4_SESSIONID_SIZE);
if (args->sequenceid != 1) {
eprintf("[cb] 1st seq#=%d is not 1\n", args->sequenceid);
res->status = NFS4ERR_SEQ_MISORDERED;
goto out;
}
cb_session->cb_is_valid_state = TRUE;
} else {
if (memcmp(cb_session->cb_sessionid, args->sessionid,
NFS4_SESSIONID_SIZE)) {
eprintf("[cb] received sessionid doesn't match saved info\n");
print_hexbuf(1, (unsigned char *)"received sessionid",
(unsigned char *)args->sessionid, NFS4_SESSIONID_SIZE);
print_hexbuf(1, (unsigned char *)"saved sessionid",
cb_session->cb_sessionid, NFS4_SESSIONID_SIZE);
res->status = NFS4ERR_BADSESSION;
goto out;
}
}
/* 20.9.3.: If the difference between csa_sequenceid and the client's
* cachedsequence ID at the slot ID is two (2) or more, or if
* csa_sequenceid is less than the cached sequence ID (accounting for
* wraparound of the unsigned sequence ID value), then the client
* MUST return NFS4ERR_SEQ_MISORDERED.
*/
if (args->sequenceid < cb_session->cb_seqnum ||
(args->sequenceid - cb_session->cb_seqnum >= 2)) {
eprintf("[cb] bad received seq#=%d, expected=%d\n",
args->sequenceid, cb_session->cb_seqnum+1);
res->status = NFS4ERR_SEQ_MISORDERED;
goto out;
}
/* we only support 1 slot for the back channel so slotid MUST be 0 */
if (args->slotid != 0) {
eprintf("[cb] received unexpected slotid=%d\n", args->slotid);
res->status = NFS4ERR_BADSLOT;
goto out;
}
if (args->highest_slotid != 0) {
eprintf("[cb] received unexpected highest_slotid=%d\n",
args->highest_slotid);
res->status = NFS4ERR_BAD_HIGH_SLOT;
goto out;
}
if (args->sequenceid == cb_session->cb_seqnum) {
// check if the request is same as the original, if different need
// to return NFS4ERR_SEQ_FALSE_RETRY
if (!cb_session->cb_cache_this) {
res->status = NFS4_OK;
status = NFS4ERR_RETRY_UNCACHED_REP;
goto out;
} else {
res->status = NFS4ERR_REP_TOO_BIG_TO_CACHE;
goto out;
}
}
if (cb_session->cb_seqnum + 1 == 0)
cb_session->cb_seqnum = 0;
else
cb_session->cb_seqnum = args->sequenceid;
cb_session->cb_cache_this = args->cachethis;
memcpy(res->ok.sessionid, args->sessionid, NFS4_SESSIONID_SIZE);
res->ok.sequenceid = args->sequenceid;
res->ok.slotid = args->slotid;
res->ok.highest_slotid = args->highest_slotid;
res->ok.target_highest_slotid = args->highest_slotid;
out:
dprintf(CBSLVL, " OP_CB_SEQUENCE { seqid %u, slot %u, cachethis %d } "
"%s\n", args->sequenceid, args->slotid, args->cachethis,
nfs_error_string(res->status));
return status;
}
/* OP_CB_RECALL */
typedef struct _nfs41_cb_recall {
nfs41_rpc_clnt *rpc_clnt;
struct cb_recall_args *args;
} nfs41_cb_recall;
static unsigned int WINAPI _handle_cb_recall(void *args)
{
nfs41_cb_recall *cb_args = (nfs41_cb_recall *)args;
nfs41_path_fh path_fh;
dprintf(1, "_handle_cb_recall: start\n");
print_hexbuf(3, (unsigned char *)"_handle_cb_recall: fh ",
cb_args->args->fh.fh, cb_args->args->fh.len);
print_hexbuf(3, (unsigned char *)"_handle_cb_recall: stateid ",
cb_args->args->stateid.other, 12);
ZeroMemory(&path_fh, sizeof(nfs41_path_fh));
memcpy(&path_fh.fh, &cb_args->args->fh, sizeof(nfs41_fh));
path_fh.fh.superblock = NULL;
path_fh.path = NULL;
path_fh.name.len = 0;
dprintf(1, "_handle_cb_recall: sending nfs41_delegreturn\n");
nfs41_delegreturn(cb_args->rpc_clnt->client->session, &path_fh,
&cb_args->args->stateid);
free(cb_args);
dprintf(1, "_handle_cb_recall: end\n");
return 1;
}
static enum_t handle_cb_recall(
IN nfs41_rpc_clnt *rpc_clnt,
IN struct cb_recall_args *args,
OUT struct cb_recall_res *res)
{
nfs41_cb_recall *cb_args;
res->status = NFS4_OK;
dprintf(CBSLVL, "OP_CB_RECALL\n");
cb_args = calloc(1, sizeof(nfs41_cb_recall));
if (cb_args == NULL) {
res->status = NFS4ERR_RESOURCE;
goto out;
}
cb_args->rpc_clnt = rpc_clnt;
cb_args->args = args;
_beginthreadex(NULL, 0, _handle_cb_recall, cb_args, 0, NULL);
out:
return res->status;
}
/* CB_COMPOUND */
static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
{
struct cb_compound_args args = { 0 };
struct cb_compound_res *res = NULL;
struct cb_argop *argop;
struct cb_resop *resop;
XDR *xdr = (XDR*)req->xdr;
uint32_t i, status = NFS4_OK;
dprintf(CBSLVL, "--> handle_compound()\n");
/* decode the arguments */
proc_cb_compound_args(xdr, &args);
dprintf(CBSLVL, "CB_COMPOUND('%s', %u)\n", args.tag.str, args.argarray_count);
if (args.minorversion != 1) {
status = NFS4ERR_MINOR_VERS_MISMATCH; //XXXXX
eprintf("args.minorversion %u != 1\n", args.minorversion);
goto out;
}
/* allocate the compound results */
res = calloc(1, sizeof(struct cb_compound_res));
if (res == NULL) {
status = NFS4ERR_RESOURCE;
goto out;
}
res->status = NFS4_OK;
StringCchCopyA(res->tag.str, CB_COMPOUND_MAX_TAG, g_server_tag);
res->tag.str[CB_COMPOUND_MAX_TAG-1] = 0;
res->tag.len = (uint32_t)strlen(res->tag.str);
res->resarray = calloc(args.argarray_count, sizeof(struct cb_resop));
if (res->resarray == NULL) {
res->status = NFS4ERR_RESOURCE;
goto out;
}
/* handle each operation in the compound */
for (i = 0; i < args.argarray_count && res->status == NFS4_OK; i++) {
argop = &args.argarray[i];
resop = &res->resarray[i];
/* 20.9.3: The error NFS4ERR_SEQUENCE_POS MUST be returned
* when CB_SEQUENCE is found in any position in a CB_COMPOUND
* beyond the first. If any other operation is in the first
* position of CB_COMPOUND, NFS4ERR_OP_NOT_IN_SESSION MUST
* be returned.
*/
if (i == 0 && argop->opnum != OP_CB_SEQUENCE) {
res->status = NFS4ERR_OP_NOT_IN_SESSION;
goto out;
}
if (i != 0 && argop->opnum == OP_CB_SEQUENCE) {
res->status = NFS4ERR_SEQUENCE_POS;
goto out;
}
resop->opnum = argop->opnum;
if (status == NFS4ERR_RETRY_UNCACHED_REP) {
res->status = status;
break;
}
switch (argop->opnum) {
case OP_CB_LAYOUTRECALL:
dprintf(1, "OP_CB_LAYOUTRECALL\n");
res->status = handle_cb_layoutrecall(rpc_clnt,
&argop->args.layoutrecall, &resop->res.layoutrecall);
break;
case OP_CB_RECALL_SLOT:
dprintf(1, "OP_CB_RECALL_SLOT\n");
res->status = handle_cb_recall_slot(&argop->args.recall_slot,
&resop->res.recall_slot);
break;
case OP_CB_SEQUENCE:
dprintf(1, "OP_CB_SEQUENCE\n");
status = handle_cb_sequence(rpc_clnt, &argop->args.sequence,
&resop->res.sequence);
if (status == NFS4_OK)
res->status = resop->res.sequence.status;
break;
case OP_CB_GETATTR:
dprintf(1, "OP_CB_GETATTR\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_RECALL:
dprintf(1, "OP_CB_RECALL\n");
res->status = handle_cb_recall(rpc_clnt,
&argop->args.recall, &resop->res.recall);
break;
case OP_CB_NOTIFY:
dprintf(1, "OP_CB_NOTIFY\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_PUSH_DELEG:
dprintf(1, "OP_CB_PUSH_DELEG\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_RECALL_ANY:
dprintf(1, "OP_CB_RECALL_ANY\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_RECALLABLE_OBJ_AVAIL:
dprintf(1, "OP_CB_RECALLABLE_OBJ_AVAIL\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_WANTS_CANCELLED:
dprintf(1, "OP_CB_WANTS_CANCELLED\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_NOTIFY_LOCK:
dprintf(1, "OP_CB_NOTIFY_LOCK\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_NOTIFY_DEVICEID:
dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
res->status = NFS4ERR_NOTSUPP;
break;
case OP_CB_ILLEGAL:
dprintf(1, "OP_CB_ILLEGAL\n");
res->status = NFS4ERR_NOTSUPP;
break;
default:
eprintf("operation %u not supported\n", argop->opnum);
res->status = NFS4ERR_NOTSUPP;
goto out;
}
res->resarray_count++;
}
out:
/* free the arguments */
xdr->x_op = XDR_FREE;
proc_cb_compound_args(xdr, &args);
*reply = res;
dprintf(CBSLVL, "<-- handle_compound() returning %s (%u results)\n",
nfs_error_string(res->status), res->resarray_count);
}
int nfs41_handle_callback(void *rpc_clnt, void *cb, struct cb_compound_res **reply)
{
nfs41_rpc_clnt *rpc = (nfs41_rpc_clnt *)rpc_clnt;
cb_req *request = (cb_req *)cb;
uint32_t status = 0;
dprintf(1, "nfs41_handle_callback: received call\n");
if (request->rq_prog != NFS41_RPC_CBPROGRAM) {
eprintf("invalid rpc program %u\n", request->rq_prog);
status = 2;
goto out;
}
switch (request->rq_proc) {
case CB_NULL:
dprintf(1, "CB_NULL\n");
break;
case CB_COMPOUND:
dprintf(1, "CB_COMPOUND\n");
handle_cb_compound(rpc, request, reply);
break;
default:
dprintf(1, "invalid rpc procedure %u\n", request->rq_proc);
status = 3;
goto out;
}
out:
return status;
}

539
daemon/callback_xdr.c Normal file
View file

@ -0,0 +1,539 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include "nfs41_callback.h"
#include "nfs41_ops.h"
#include "daemon_debug.h"
#define CBXLVL 2 /* dprintf level for callback xdr logging */
#define CBX_ERR(msg) dprintf((CBXLVL), __FUNCTION__ ": failed at " msg "\n")
/* common types */
static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
{
return xdr_u_int32_t(xdr, &stateid->seqid)
&& xdr_opaque(xdr, (char*)stateid->other, 12);
}
static bool_t common_fh(XDR *xdr, nfs41_fh *fh)
{
return xdr_u_int32_t(xdr, &fh->len)
&& fh->len <= NFS4_FHSIZE
&& xdr_opaque(xdr, (char*)fh->fh, fh->len);
}
static bool_t common_fsid(XDR *xdr, nfs41_fsid *fsid)
{
return xdr_u_int64_t(xdr, &fsid->major)
&& xdr_u_int64_t(xdr, &fsid->minor);
}
/* OP_CB_LAYOUTRECALL */
static bool_t op_cb_layoutrecall_file(XDR *xdr, struct cb_recall_file *args)
{
bool_t result;
result = common_fh(xdr, &args->fh);
if (!result) { CBX_ERR("layoutrecall_file.fh"); goto out; }
result = xdr_u_int64_t(xdr, &args->offset);
if (!result) { CBX_ERR("layoutrecall_file.offset"); goto out; }
result = xdr_u_int64_t(xdr, &args->length);
if (!result) { CBX_ERR("layoutrecall_file.length"); goto out; }
result = common_stateid(xdr, &args->stateid);
if (!result) { CBX_ERR("layoutrecall_file.stateid"); goto out; }
out:
return result;
}
static bool_t op_cb_layoutrecall_fsid(XDR *xdr, union cb_recall_file_args *args)
{
bool_t result;
result = common_fsid(xdr, &args->fsid);
if (!result) { CBX_ERR("layoutrecall_fsid.fsid"); goto out; }
out:
return result;
}
static const struct xdr_discrim cb_layoutrecall_discrim[] = {
{ PNFS_RETURN_FILE, (xdrproc_t)op_cb_layoutrecall_file },
{ PNFS_RETURN_FSID, (xdrproc_t)op_cb_layoutrecall_fsid },
{ PNFS_RETURN_ALL, (xdrproc_t)xdr_void },
{ 0, NULL_xdrproc_t }
};
static bool_t op_cb_layoutrecall_args(XDR *xdr, struct cb_layoutrecall_args *args)
{
bool_t result;
result = xdr_enum(xdr, (enum_t*)&args->type);
if (!result) { CBX_ERR("layoutrecall_args.type"); goto out; }
result = xdr_enum(xdr, (enum_t*)&args->iomode);
if (!result) { CBX_ERR("layoutrecall_args.iomode"); goto out; }
result = xdr_bool(xdr, &args->changed);
if (!result) { CBX_ERR("layoutrecall_args.changed"); goto out; }
result = xdr_union(xdr, (enum_t*)&args->recall.type,
(char*)&args->recall.args, cb_layoutrecall_discrim, NULL_xdrproc_t);
if (!result) { CBX_ERR("layoutrecall_args.recall"); goto out; }
out:
return result;
}
static bool_t op_cb_layoutrecall_res(XDR *xdr, struct cb_layoutrecall_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("layoutrecall_res.status"); goto out; }
out:
return result;
}
/* OP_CB_RECALL_SLOT */
static bool_t op_cb_recall_slot_args(XDR *xdr, struct cb_recall_slot_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("recall_slot.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_recall_slot_res(XDR *xdr, struct cb_recall_slot_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("recall_slot.status"); goto out; }
out:
return result;
}
/* OP_CB_SEQUENCE */
static bool_t op_cb_sequence_ref(XDR *xdr, struct cb_sequence_ref *args)
{
bool_t result;
result = xdr_u_int32_t(xdr, &args->sequenceid);
if (!result) { CBX_ERR("sequence_ref.sequenceid"); goto out; }
result = xdr_u_int32_t(xdr, &args->slotid);
if (!result) { CBX_ERR("sequence_ref.slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_sequence_ref_list(XDR *xdr, struct cb_sequence_ref_list *args)
{
bool_t result;
result = xdr_opaque(xdr, args->sessionid, NFS4_SESSIONID_SIZE);
if (!result) { CBX_ERR("sequence_ref_list.sessionid"); goto out; }
result = xdr_array(xdr, (char**)&args->calls, &args->call_count,
64, sizeof(struct cb_sequence_ref), (xdrproc_t)op_cb_sequence_ref);
if (!result) { CBX_ERR("sequence_ref_list.calls"); goto out; }
out:
return result;
}
static bool_t op_cb_sequence_args(XDR *xdr, struct cb_sequence_args *args)
{
bool_t result;
dprintf(1, "decoding sequence args\n");
result = xdr_opaque(xdr, args->sessionid, NFS4_SESSIONID_SIZE);
if (!result) { CBX_ERR("sequence_args.sessionid"); goto out; }
result = xdr_u_int32_t(xdr, &args->sequenceid);
if (!result) { CBX_ERR("sequence_args.sequenceid"); goto out; }
result = xdr_u_int32_t(xdr, &args->slotid);
if (!result) { CBX_ERR("sequence_args.slotid"); goto out; }
result = xdr_u_int32_t(xdr, &args->highest_slotid);
if (!result) { CBX_ERR("sequence_args.highest_slotid"); goto out; }
result = xdr_bool(xdr, &args->cachethis);
if (!result) { CBX_ERR("sequence_args.cachethis"); goto out; }
result = xdr_array(xdr, (char**)&args->ref_lists,
&args->ref_list_count, 64, sizeof(struct cb_sequence_ref_list),
(xdrproc_t)op_cb_sequence_ref_list);
if (!result) { CBX_ERR("sequence_args.ref_lists"); goto out; }
out:
return result;
}
static bool_t op_cb_sequence_res_ok(XDR *xdr, struct cb_sequence_res_ok *res)
{
bool_t result;
result = xdr_opaque(xdr, res->sessionid, NFS4_SESSIONID_SIZE);
if (!result) { CBX_ERR("sequence_res.sessionid"); goto out; }
result = xdr_u_int32_t(xdr, &res->sequenceid);
if (!result) { CBX_ERR("sequence_res.sequenceid"); goto out; }
result = xdr_u_int32_t(xdr, &res->slotid);
if (!result) { CBX_ERR("sequence_res.slotid"); goto out; }
result = xdr_u_int32_t(xdr, &res->highest_slotid);
if (!result) { CBX_ERR("sequence_res.highest_slotid"); goto out; }
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("sequence_res.target_highest_slotid"); goto out; }
out:
return result;
}
static const struct xdr_discrim cb_sequence_res_discrim[] = {
{ NFS4_OK, (xdrproc_t)op_cb_sequence_res_ok },
{ 0, NULL_xdrproc_t }
};
static bool_t op_cb_sequence_res(XDR *xdr, struct cb_sequence_res *res)
{
bool_t result;
result = xdr_union(xdr, &res->status, (char*)&res->ok,
cb_sequence_res_discrim, (xdrproc_t)xdr_void);
if (!result) { CBX_ERR("seq:argop.args"); goto out; }
out:
return result;
}
/* OP_CB_GETATTR */
static bool_t op_cb_getattr_args(XDR *xdr, struct cb_getattr_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("getattr.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_getattr_res(XDR *xdr, struct cb_getattr_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("getattr.status"); goto out; }
out:
return result;
}
/* OP_CB_RECALL */
static bool_t op_cb_recall_args(XDR *xdr, struct cb_recall_args *args)
{
bool_t result;
dprintf(1, "decoding recall args\n");
result = common_stateid(xdr, &args->stateid);
if (!result) { CBX_ERR("recall.stateid"); goto out; }
result = xdr_bool(xdr, &args->truncate);
if (!result) { CBX_ERR("recall.truncate"); goto out; }
result = common_fh(xdr, &args->fh);
if (!result) { CBX_ERR("recall.fh"); goto out; }
out:
return result;
}
static bool_t op_cb_recall_res(XDR *xdr, struct cb_recall_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("recall.status"); goto out; }
out:
return result;
}
/* OP_CB_NOTIFY */
static bool_t op_cb_notify_args(XDR *xdr, struct cb_notify_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("notify.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_notify_res(XDR *xdr, struct cb_notify_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("notify.status"); goto out; }
out:
return result;
}
/* OP_CB_PUSH_DELEG */
static bool_t op_cb_push_deleg_args(XDR *xdr, struct cb_push_deleg_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("push_deleg.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_push_deleg_res(XDR *xdr, struct cb_push_deleg_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("push_deleg.status"); goto out; }
out:
return result;
}
/* OP_CB_RECALL_ANY */
static bool_t op_cb_recall_any_args(XDR *xdr, struct cb_recall_any_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("recall_any.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_recall_any_res(XDR *xdr, struct cb_recall_any_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("recall_any.status"); goto out; }
out:
return result;
}
/* OP_CB_RECALLABLE_OBJ_AVAIL */
static bool_t op_cb_recallable_obj_avail_args(XDR *xdr, struct cb_recallable_obj_avail_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("recallable_obj_avail.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_recallable_obj_avail_res(XDR *xdr, struct cb_recallable_obj_avail_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("recallable_obj_avail.status"); goto out; }
out:
return result;
}
/* OP_CB_WANTS_CANCELLED */
static bool_t op_cb_wants_cancelled_args(XDR *xdr, struct cb_wants_cancelled_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("wants_cancelled.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_wants_cancelled_res(XDR *xdr, struct cb_wants_cancelled_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("wants_cancelled.status"); goto out; }
out:
return result;
}
/* OP_CB_NOTIFY_LOCK */
static bool_t op_cb_notify_lock_args(XDR *xdr, struct cb_notify_lock_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("notify_lock.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_notify_lock_res(XDR *xdr, struct cb_notify_lock_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("notify_lock.status"); goto out; }
out:
return result;
}
/* OP_CB_NOTIFY_DEVICEID */
static bool_t op_cb_notify_deviceid_args(XDR *xdr, struct cb_notify_deviceid_args *res)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("notify_deviceid.target_highest_slotid"); goto out; }
out:
return result;
}
static bool_t op_cb_notify_deviceid_res(XDR *xdr, struct cb_notify_deviceid_res *res)
{
bool_t result;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("notify_deviceid.status"); goto out; }
out:
return result;
}
/* CB_COMPOUND */
static bool_t cb_compound_tag(XDR *xdr, struct cb_compound_tag *args)
{
return xdr_u_int32_t(xdr, &args->len)
&& args->len <= CB_COMPOUND_MAX_TAG
&& xdr_opaque(xdr, args->str, args->len);
}
static const struct xdr_discrim cb_argop_discrim[] = {
{ OP_CB_LAYOUTRECALL, (xdrproc_t)op_cb_layoutrecall_args },
{ OP_CB_RECALL_SLOT, (xdrproc_t)op_cb_recall_slot_args },
{ OP_CB_SEQUENCE, (xdrproc_t)op_cb_sequence_args },
{ OP_CB_GETATTR, (xdrproc_t)op_cb_getattr_args },
{ OP_CB_RECALL, (xdrproc_t)op_cb_recall_args },
{ OP_CB_NOTIFY, (xdrproc_t)op_cb_notify_args },
{ OP_CB_PUSH_DELEG, (xdrproc_t)op_cb_push_deleg_args },
{ OP_CB_RECALL_ANY, (xdrproc_t)op_cb_recall_any_args },
{ OP_CB_RECALLABLE_OBJ_AVAIL, (xdrproc_t)op_cb_recallable_obj_avail_args },
{ OP_CB_WANTS_CANCELLED, (xdrproc_t)op_cb_wants_cancelled_args },
{ OP_CB_NOTIFY_LOCK, (xdrproc_t)op_cb_notify_lock_args },
{ OP_CB_NOTIFY_DEVICEID, (xdrproc_t)op_cb_notify_deviceid_args },
{ OP_CB_ILLEGAL, NULL_xdrproc_t },
};
static bool_t cb_compound_argop(XDR *xdr, struct cb_argop *args)
{
bool_t result;
result = xdr_union(xdr, &args->opnum, (char*)&args->args,
cb_argop_discrim, NULL_xdrproc_t);
if (!result) { CBX_ERR("cmb:argop.args"); goto out; }
out:
return result;
}
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args)
{
bool_t result;
result = cb_compound_tag(xdr, &args->tag);
if (!result) { CBX_ERR("compound.tag"); goto out; }
result = xdr_u_int32_t(xdr, &args->minorversion);
if (!result) { CBX_ERR("compound.minorversion"); goto out; }
/* "superfluous in NFSv4.1 and MUST be ignored by the client" */
result = xdr_u_int32_t(xdr, &args->callback_ident);
if (!result) { CBX_ERR("compound.callback_ident"); goto out; }
result = xdr_array(xdr, (char**)&args->argarray,
&args->argarray_count, CB_COMPOUND_MAX_OPERATIONS,
sizeof(struct cb_argop), (xdrproc_t)cb_compound_argop);
if (!result) { CBX_ERR("compound.argarray"); goto out; }
out:
return result;
}
static const struct xdr_discrim cb_resop_discrim[] = {
{ OP_CB_LAYOUTRECALL, (xdrproc_t)op_cb_layoutrecall_res },
{ OP_CB_RECALL_SLOT, (xdrproc_t)op_cb_recall_slot_res },
{ OP_CB_SEQUENCE, (xdrproc_t)op_cb_sequence_res },
{ OP_CB_GETATTR, (xdrproc_t)op_cb_getattr_res },
{ OP_CB_RECALL, (xdrproc_t)op_cb_recall_res },
{ OP_CB_NOTIFY, (xdrproc_t)op_cb_notify_res },
{ OP_CB_PUSH_DELEG, (xdrproc_t)op_cb_push_deleg_res },
{ OP_CB_RECALL_ANY, (xdrproc_t)op_cb_recall_any_res },
{ OP_CB_RECALLABLE_OBJ_AVAIL, (xdrproc_t)op_cb_recallable_obj_avail_res },
{ OP_CB_WANTS_CANCELLED, (xdrproc_t)op_cb_wants_cancelled_res },
{ OP_CB_NOTIFY_LOCK, (xdrproc_t)op_cb_notify_lock_res },
{ OP_CB_NOTIFY_DEVICEID, (xdrproc_t)op_cb_notify_deviceid_res },
{ OP_CB_ILLEGAL, NULL_xdrproc_t },
};
static bool_t cb_compound_resop(XDR *xdr, struct cb_resop *res)
{
bool_t result;
result = xdr_union(xdr, &res->opnum, (char*)&res->res,
cb_resop_discrim, NULL_xdrproc_t);
if (!result) { CBX_ERR("resop.res"); goto out; }
out:
return result;
}
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
{
bool_t result;
if (res == NULL)
return TRUE;
result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("compound_res.status"); goto out; }
result = cb_compound_tag(xdr, &res->tag);
if (!result) { CBX_ERR("compound_res.tag"); goto out; }
result = xdr_array(xdr, (char**)&res->resarray,
&res->resarray_count, CB_COMPOUND_MAX_OPERATIONS,
sizeof(struct cb_resop), (xdrproc_t)cb_compound_resop);
if (!result) { CBX_ERR("compound_res.resarray"); goto out; }
out:
free(res->resarray);
free(res);
return result;
}

440
daemon/daemon_debug.c Normal file
View file

@ -0,0 +1,440 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <windows.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "from_kernel.h"
#include "nfs41_driver.h"
#include "nfs41_ops.h"
static int g_debug_level = DEFAULT_DEBUG_LEVEL;
void set_debug_level(int level) { g_debug_level = level; }
void dprintf(int level, LPCSTR format, ...)
{
if (level <= g_debug_level) {
va_list args;
va_start(args, format);
printf("%04x: ", GetCurrentThreadId());
vprintf(format, args);
va_end(args);
}
}
void eprintf(LPCSTR format, ...)
{
va_list args;
va_start(args, format);
fprintf(stderr, "%04x: ", GetCurrentThreadId());
vfprintf(stderr, format, args);
va_end(args);
}
void print_hexbuf(int level, unsigned char *title, unsigned char *buf, int len)
{
int j, k;
if (level > g_debug_level) return;
printf("%s", title);
for(j = 0, k = 0; j < len; j++, k++) {
printf("%02x '%c' ", buf[j], isascii(buf[j])? buf[j]:' ');
if (((k+1) % 10 == 0 && k > 0)) {
printf("\n");
}
}
printf("\n");
}
void print_create_attributes(int level, DWORD create_opts) {
if (level > g_debug_level) return;
printf("create attributes: ");
if (create_opts & FILE_DIRECTORY_FILE)
printf("DIRECTORY_FILE ");
if (create_opts & FILE_NON_DIRECTORY_FILE)
printf("NON_DIRECTORY_FILE ");
if (create_opts & FILE_WRITE_THROUGH)
printf("WRITE_THROUGH ");
if (create_opts & FILE_SEQUENTIAL_ONLY)
printf("SEQUENTIAL_ONLY ");
if (create_opts & FILE_RANDOM_ACCESS)
printf("RANDOM_ACCESS ");
if (create_opts & FILE_NO_INTERMEDIATE_BUFFERING)
printf("NO_INTERMEDIATE_BUFFERING ");
if (create_opts & FILE_SYNCHRONOUS_IO_ALERT)
printf("SYNCHRONOUS_IO_ALERT ");
if (create_opts & FILE_SYNCHRONOUS_IO_NONALERT)
printf("SYNCHRONOUS_IO_NONALERT ");
if (create_opts & FILE_CREATE_TREE_CONNECTION)
printf("CREATE_TREE_CONNECTION ");
if (create_opts & FILE_COMPLETE_IF_OPLOCKED)
printf("COMPLETE_IF_OPLOCKED ");
if (create_opts & FILE_NO_EA_KNOWLEDGE)
printf("NO_EA_KNOWLEDGE ");
if (create_opts & FILE_OPEN_REPARSE_POINT)
printf("OPEN_REPARSE_POINT ");
if (create_opts & FILE_DELETE_ON_CLOSE)
printf("DELETE_ON_CLOSE ");
if (create_opts & FILE_OPEN_BY_FILE_ID)
printf("OPEN_BY_FILE_ID ");
if (create_opts & FILE_OPEN_FOR_BACKUP_INTENT)
printf("OPEN_FOR_BACKUP_INTENT ");
if (create_opts & FILE_RESERVE_OPFILTER)
printf("RESERVE_OPFILTER");
printf("\n");
}
void print_disposition(int level, DWORD disposition) {
if (level > g_debug_level) return;
printf("userland disposition = ");
if (disposition == FILE_SUPERSEDE)
printf("FILE_SUPERSEDE\n");
else if (disposition == FILE_CREATE)
printf("FILE_CREATE\n");
else if (disposition == FILE_OPEN)
printf("FILE_OPEN\n");
else if (disposition == FILE_OPEN_IF)
printf("FILE_OPEN_IF\n");
else if (disposition == FILE_OVERWRITE)
printf("FILE_OVERWRITE\n");
else if (disposition == FILE_OVERWRITE_IF)
printf("FILE_OVERWRITE_IF\n");
}
void print_access_mask(int level, DWORD access_mask) {
if (level > g_debug_level) return;
printf("access mask: ");
if (access_mask & FILE_READ_DATA)
printf("READ ");
if (access_mask & STANDARD_RIGHTS_READ)
printf("READ_ACL ");
if (access_mask & FILE_READ_ATTRIBUTES)
printf("READ_ATTR ");
if (access_mask & FILE_READ_EA)
printf("READ_EA ");
if (access_mask & FILE_WRITE_DATA)
printf("WRITE ");
if (access_mask & STANDARD_RIGHTS_WRITE)
printf("WRITE_ACL ");
if (access_mask & FILE_WRITE_ATTRIBUTES)
printf("WRITE_ATTR ");
if (access_mask & FILE_WRITE_EA)
printf("WRITE_EA ");
if (access_mask & FILE_APPEND_DATA)
printf("APPEND ");
if (access_mask & FILE_EXECUTE)
printf("EXECUTE ");
if (access_mask & FILE_LIST_DIRECTORY)
printf("LIST ");
if (access_mask & FILE_TRAVERSE)
printf("TRAVERSE ");
if (access_mask & SYNCHRONIZE)
printf("SYNC ");
if (access_mask & FILE_DELETE_CHILD)
printf("DELETE_CHILD");
printf("\n");
}
void print_share_mode(int level, DWORD mode)
{
if (level > g_debug_level) return;
printf("share mode: ");
if (mode & FILE_SHARE_READ)
printf("READ ");
if (mode & FILE_SHARE_WRITE)
printf("WRITE ");
if (mode & FILE_SHARE_DELETE)
printf("DELETE");
printf("\n");
}
void print_file_id_both_dir_info(int level, FILE_ID_BOTH_DIR_INFO *pboth_dir_info)
{
if (level > g_debug_level) return;
printf("FILE_ID_BOTH_DIR_INFO %p %d\n", pboth_dir_info, sizeof(unsigned char *));
printf("\tNextEntryOffset=%ld %d %d\n", pboth_dir_info->NextEntryOffset, sizeof(pboth_dir_info->NextEntryOffset), sizeof(DWORD));
printf("\tFileIndex=%ld %d\n", pboth_dir_info->FileIndex, sizeof(pboth_dir_info->FileIndex));
printf("\tCreationTime=0x%x %d\n", pboth_dir_info->CreationTime.QuadPart, sizeof(pboth_dir_info->CreationTime));
printf("\tLastAccessTime=0x%x %d\n", pboth_dir_info->LastAccessTime.QuadPart, sizeof(pboth_dir_info->LastAccessTime));
printf("\tLastWriteTime=0x%x %d\n", pboth_dir_info->LastWriteTime.QuadPart, sizeof(pboth_dir_info->LastWriteTime));
printf("\tChangeTime=0x%x %d\n", pboth_dir_info->ChangeTime.QuadPart, sizeof(pboth_dir_info->ChangeTime));
printf("\tEndOfFile=0x%x %d\n", pboth_dir_info->EndOfFile.QuadPart, sizeof(pboth_dir_info->EndOfFile));
printf("\tAllocationSize=0x%x %d\n", pboth_dir_info->AllocationSize.QuadPart, sizeof(pboth_dir_info->AllocationSize));
printf("\tFileAttributes=%ld %d\n", pboth_dir_info->FileAttributes, sizeof(pboth_dir_info->FileAttributes));
printf("\tFileNameLength=%ld %d\n", pboth_dir_info->FileNameLength, sizeof(pboth_dir_info->FileNameLength));
printf("\tEaSize=%ld %d\n", pboth_dir_info->EaSize, sizeof(pboth_dir_info->EaSize));
printf("\tShortNameLength=%d %d\n", pboth_dir_info->ShortNameLength, sizeof(pboth_dir_info->ShortNameLength));
printf("\tShortName='%S' %d\n", pboth_dir_info->ShortName, sizeof(pboth_dir_info->ShortName));
printf("\tFileId=0x%x %d\n", pboth_dir_info->FileId.QuadPart, sizeof(pboth_dir_info->FileId));
printf("\tFileName='%S' %p\n", pboth_dir_info->FileName, pboth_dir_info->FileName);
}
void print_opcode(int level, DWORD opcode)
{
dprintf(level, (LPCSTR)opcode2string(opcode));
}
const char* opcode2string(DWORD opcode)
{
switch(opcode) {
case NFS41_SHUTDOWN: return "NFS41_SHUTDOWN";
case NFS41_MOUNT: return "NFS41_MOUNT";
case NFS41_UNMOUNT: return "NFS41_UNMOUNT";
case NFS41_OPEN: return "NFS41_OPEN";
case NFS41_CLOSE: return "NFS41_CLOSE";
case NFS41_READ: return "NFS41_READ";
case NFS41_WRITE: return "NFS41_WRITE";
case NFS41_LOCK: return "NFS41_LOCK";
case NFS41_UNLOCK: return "NFS41_UNLOCK";
case NFS41_DIR_QUERY: return "NFS41_DIR_QUERY";
case NFS41_FILE_QUERY: return "NFS41_FILE_QUERY";
case NFS41_FILE_SET: return "NFS41_FILE_SET";
case NFS41_EA_SET: return "NFS41_EA_SET";
case NFS41_VOLUME_QUERY: return "NFS41_VOLUME_QUERY";
default: return "UNKNOWN";
}
}
const char* nfs_opnum_to_string(int opnum)
{
switch (opnum)
{
case OP_ACCESS: return "ACCESS";
case OP_CLOSE: return "CLOSE";
case OP_COMMIT: return "COMMIT";
case OP_CREATE: return "CREATE";
case OP_DELEGPURGE: return "DELEGPURGE";
case OP_DELEGRETURN: return "DELEGRETURN";
case OP_GETATTR: return "GETATTR";
case OP_GETFH: return "GETFH";
case OP_LINK: return "LINK";
case OP_LOCK: return "LOCK";
case OP_LOCKT: return "LOCKT";
case OP_LOCKU: return "LOCKU";
case OP_LOOKUP: return "LOOKUP";
case OP_LOOKUPP: return "LOOKUPP";
case OP_NVERIFY: return "NVERIFY";
case OP_OPEN: return "OPEN";
case OP_OPENATTR: return "OPENATTR";
case OP_OPEN_CONFIRM: return "OPEN_CONFIRM";
case OP_OPEN_DOWNGRADE: return "OPEN_DOWNGRADE";
case OP_PUTFH: return "PUTFH";
case OP_PUTPUBFH: return "PUTPUBFH";
case OP_PUTROOTFH: return "PUTROOTFH";
case OP_READ: return "READ";
case OP_READDIR: return "READDIR";
case OP_READLINK: return "READLINK";
case OP_REMOVE: return "REMOVE";
case OP_RENAME: return "RENAME";
case OP_RENEW: return "RENEW";
case OP_RESTOREFH: return "RESTOREFH";
case OP_SAVEFH: return "SAVEFH";
case OP_SECINFO: return "SECINFO";
case OP_SETATTR: return "SETATTR";
case OP_SETCLIENTID: return "SETCLIENTID";
case OP_SETCLIENTID_CONFIRM: return "SETCLIENTID_CONFIRM";
case OP_VERIFY: return "VERIFY";
case OP_WRITE: return "WRITE";
case OP_RELEASE_LOCKOWNER: return "RELEASE_LOCKOWNER";
case OP_BACKCHANNEL_CTL: return "BACKCHANNEL_CTL";
case OP_BIND_CONN_TO_SESSION: return "BIND_CONN_TO_SESSION";
case OP_EXCHANGE_ID: return "EXCHANGE_ID";
case OP_CREATE_SESSION: return "CREATE_SESSION";
case OP_DESTROY_SESSION: return "DESTROY_SESSION";
case OP_FREE_STATEID: return "FREE_STATEID";
case OP_GET_DIR_DELEGATION: return "GET_DIR_DELEGATION";
case OP_GETDEVICEINFO: return "GETDEVICEINFO";
case OP_GETDEVICELIST: return "GETDEVICELIST";
case OP_LAYOUTCOMMIT: return "LAYOUTCOMMIT";
case OP_LAYOUTGET: return "LAYOUTGET";
case OP_LAYOUTRETURN: return "LAYOUTRETURN";
case OP_SECINFO_NO_NAME: return "SECINFO_NO_NAME";
case OP_SEQUENCE: return "SEQUENCE";
case OP_SET_SSV: return "SET_SSV";
case OP_TEST_STATEID: return "TEST_STATEID";
case OP_WANT_DELEGATION: return "WANT_DELEGATION";
case OP_DESTROY_CLIENTID: return "DESTROY_CLIENTID";
case OP_RECLAIM_COMPLETE: return "RECLAIM_COMPLETE";
case OP_ILLEGAL: return "ILLEGAL";
default: return "invalid nfs opnum";
}
}
const char* nfs_error_string(int status)
{
switch (status)
{
case NFS4_OK: return "NFS4_OK";
case NFS4ERR_PERM: return "NFS4ERR_PERM";
case NFS4ERR_NOENT: return "NFS4ERR_NOENT";
case NFS4ERR_IO: return "NFS4ERR_IO";
case NFS4ERR_NXIO: return "NFS4ERR_NXIO";
case NFS4ERR_ACCESS: return "NFS4ERR_ACCESS";
case NFS4ERR_EXIST: return "NFS4ERR_EXIST";
case NFS4ERR_XDEV: return "NFS4ERR_XDEV";
case NFS4ERR_NOTDIR: return "NFS4ERR_NOTDIR";
case NFS4ERR_ISDIR: return "NFS4ERR_ISDIR";
case NFS4ERR_INVAL: return "NFS4ERR_INVAL";
case NFS4ERR_FBIG: return "NFS4ERR_FBIG";
case NFS4ERR_NOSPC: return "NFS4ERR_NOSPC";
case NFS4ERR_ROFS: return "NFS4ERR_ROFS";
case NFS4ERR_MLINK: return "NFS4ERR_MLINK";
case NFS4ERR_NAMETOOLONG: return "NFS4ERR_NAMETOOLONG";
case NFS4ERR_NOTEMPTY: return "NFS4ERR_NOTEMPTY";
case NFS4ERR_DQUOT: return "NFS4ERR_DQUOT";
case NFS4ERR_STALE: return "NFS4ERR_STALE";
case NFS4ERR_BADHANDLE: return "NFS4ERR_BADHANDLE";
case NFS4ERR_BAD_COOKIE: return "NFS4ERR_BAD_COOKIE";
case NFS4ERR_NOTSUPP: return "NFS4ERR_NOTSUPP";
case NFS4ERR_TOOSMALL: return "NFS4ERR_TOOSMALL";
case NFS4ERR_SERVERFAULT: return "NFS4ERR_SERVERFAULT";
case NFS4ERR_BADTYPE: return "NFS4ERR_BADTYPE";
case NFS4ERR_DELAY: return "NFS4ERR_DELAY";
case NFS4ERR_SAME: return "NFS4ERR_SAME";
case NFS4ERR_DENIED: return "NFS4ERR_DENIED";
case NFS4ERR_EXPIRED: return "NFS4ERR_EXPIRED";
case NFS4ERR_LOCKED: return "NFS4ERR_LOCKED";
case NFS4ERR_GRACE: return "NFS4ERR_GRACE";
case NFS4ERR_FHEXPIRED: return "NFS4ERR_FHEXPIRED";
case NFS4ERR_SHARE_DENIED: return "NFS4ERR_SHARE_DENIED";
case NFS4ERR_WRONGSEC: return "NFS4ERR_WRONGSEC";
case NFS4ERR_CLID_INUSE: return "NFS4ERR_CLID_INUSE";
case NFS4ERR_RESOURCE: return "NFS4ERR_RESOURCE";
case NFS4ERR_MOVED: return "NFS4ERR_MOVED";
case NFS4ERR_NOFILEHANDLE: return "NFS4ERR_NOFILEHANDLE";
case NFS4ERR_MINOR_VERS_MISMATCH: return "NFS4ERR_MINOR_VERS_MISMATCH";
case NFS4ERR_STALE_CLIENTID: return "NFS4ERR_STALE_CLIENTID";
case NFS4ERR_STALE_STATEID: return "NFS4ERR_STALE_STATEID";
case NFS4ERR_OLD_STATEID: return "NFS4ERR_OLD_STATEID";
case NFS4ERR_BAD_STATEID: return "NFS4ERR_BAD_STATEID";
case NFS4ERR_BAD_SEQID: return "NFS4ERR_BAD_SEQID";
case NFS4ERR_NOT_SAME: return "NFS4ERR_NOT_SAME";
case NFS4ERR_LOCK_RANGE: return "NFS4ERR_LOCK_RANGE";
case NFS4ERR_SYMLINK: return "NFS4ERR_SYMLINK";
case NFS4ERR_RESTOREFH: return "NFS4ERR_RESTOREFH";
case NFS4ERR_LEASE_MOVED: return "NFS4ERR_LEASE_MOVED";
case NFS4ERR_ATTRNOTSUPP: return "NFS4ERR_ATTRNOTSUPP";
case NFS4ERR_NO_GRACE: return "NFS4ERR_NO_GRACE";
case NFS4ERR_RECLAIM_BAD: return "NFS4ERR_RECLAIM_BAD";
case NFS4ERR_RECLAIM_CONFLICT: return "NFS4ERR_RECLAIM_CONFLICT";
case NFS4ERR_BADXDR: return "NFS4ERR_BADXDR";
case NFS4ERR_LOCKS_HELD: return "NFS4ERR_LOCKS_HELD";
case NFS4ERR_OPENMODE: return "NFS4ERR_OPENMODE";
case NFS4ERR_BADOWNER: return "NFS4ERR_BADOWNER";
case NFS4ERR_BADCHAR: return "NFS4ERR_BADCHAR";
case NFS4ERR_BADNAME: return "NFS4ERR_BADNAME";
case NFS4ERR_BAD_RANGE: return "NFS4ERR_BAD_RANGE";
case NFS4ERR_LOCK_NOTSUPP: return "NFS4ERR_LOCK_NOTSUPP";
case NFS4ERR_OP_ILLEGAL: return "NFS4ERR_OP_ILLEGAL";
case NFS4ERR_DEADLOCK: return "NFS4ERR_DEADLOCK";
case NFS4ERR_FILE_OPEN: return "NFS4ERR_FILE_OPEN";
case NFS4ERR_ADMIN_REVOKED: return "NFS4ERR_ADMIN_REVOKED";
case NFS4ERR_CB_PATH_DOWN: return "NFS4ERR_CB_PATH_DOWN";
case NFS4ERR_BADIOMODE: return "NFS4ERR_BADIOMODE";
case NFS4ERR_BADLAYOUT: return "NFS4ERR_BADLAYOUT";
case NFS4ERR_BAD_SESSION_DIGEST: return "NFS4ERR_BAD_SESSION_DIGEST";
case NFS4ERR_BADSESSION: return "NFS4ERR_BADSESSION";
case NFS4ERR_BADSLOT: return "NFS4ERR_BADSLOT";
case NFS4ERR_COMPLETE_ALREADY: return "NFS4ERR_COMPLETE_ALREADY";
case NFS4ERR_CONN_NOT_BOUND_TO_SESSION: return "NFS4ERR_CONN_NOT_BOUND_TO_SESSION";
case NFS4ERR_DELEG_ALREADY_WANTED: return "NFS4ERR_DELEG_ALREADY_WANTED";
case NFS4ERR_BACK_CHAN_BUSY: return "NFS4ERR_BACK_CHAN_BUSY";
case NFS4ERR_LAYOUTTRYLATER: return "NFS4ERR_LAYOUTTRYLATER";
case NFS4ERR_LAYOUTUNAVAILABLE: return "NFS4ERR_LAYOUTUNAVAILABLE";
case NFS4ERR_NOMATCHING_LAYOUT: return "NFS4ERR_NOMATCHING_LAYOUT";
case NFS4ERR_RECALLCONFLICT: return "NFS4ERR_RECALLCONFLICT";
case NFS4ERR_UNKNOWN_LAYOUTTYPE: return "NFS4ERR_UNKNOWN_LAYOUTTYPE";
case NFS4ERR_SEQ_MISORDERED: return "NFS4ERR_SEQ_MISORDERED";
case NFS4ERR_SEQUENCE_POS: return "NFS4ERR_SEQUENCE_POS";
case NFS4ERR_REQ_TOO_BIG: return "NFS4ERR_REQ_TOO_BIG";
case NFS4ERR_REP_TOO_BIG: return "NFS4ERR_REP_TOO_BIG";
case NFS4ERR_REP_TOO_BIG_TO_CACHE: return "NFS4ERR_REP_TOO_BIG_TO_CACHE";
case NFS4ERR_RETRY_UNCACHED_REP: return "NFS4ERR_RETRY_UNCACHED_REP";
case NFS4ERR_UNSAFE_COMPOUND: return "NFS4ERR_UNSAFE_COMPOUND";
case NFS4ERR_TOO_MANY_OPS: return "NFS4ERR_TOO_MANY_OPS";
case NFS4ERR_OP_NOT_IN_SESSION: return "NFS4ERR_OP_NOT_IN_SESSION";
case NFS4ERR_HASH_ALG_UNSUPP: return "NFS4ERR_HASH_ALG_UNSUPP";
case NFS4ERR_CLIENTID_BUSY: return "NFS4ERR_CLIENTID_BUSY";
case NFS4ERR_PNFS_IO_HOLE: return "NFS4ERR_PNFS_IO_HOLE";
case NFS4ERR_SEQ_FALSE_RETRY: return "NFS4ERR_SEQ_FALSE_RETRY";
case NFS4ERR_BAD_HIGH_SLOT: return "NFS4ERR_BAD_HIGH_SLOT";
case NFS4ERR_DEADSESSION: return "NFS4ERR_DEADSESSION";
case NFS4ERR_ENCR_ALG_UNSUPP: return "NFS4ERR_ENCR_ALG_UNSUPP";
case NFS4ERR_PNFS_NO_LAYOUT: return "NFS4ERR_PNFS_NO_LAYOUT";
case NFS4ERR_NOT_ONLY_OP: return "NFS4ERR_NOT_ONLY_OP";
case NFS4ERR_WRONG_CRED: return "NFS4ERR_WRONG_CRED";
case NFS4ERR_WRONG_TYPE: return "NFS4ERR_WRONG_TYPE";
case NFS4ERR_DIRDELEG_UNAVAIL: return "NFS4ERR_DIRDELEG_UNAVAIL";
case NFS4ERR_REJECT_DELEG: return "NFS4ERR_REJECT_DELEG";
case NFS4ERR_RETURNCONFLICT: return "NFS4ERR_RETURNCONFLICT";
case NFS4ERR_DELEG_REVOKED: return "NFS4ERR_DELEG_REVOKED";
default: return "invalid nfs error code";
}
}
void print_condwait_status(int level, int status)
{
if (level > g_debug_level) return;
switch(status) {
case WAIT_ABANDONED: printf("WAIT_ABANDONED\n"); break;
case WAIT_OBJECT_0: printf("WAIT_OBJECT_0\n"); break;
case WAIT_TIMEOUT: printf("WAIT_TIMEOUT\n"); break;
case WAIT_FAILED: printf("WAIT_FAILED %d\n", GetLastError());
default: printf("unknown status =%d\n", status);
}
}
void print_sr_status_flags(int level, int flags)
{
if (level > g_debug_level) return;
printf("%04x: sr_status_flags: ", GetCurrentThreadId());
if (flags & SEQ4_STATUS_CB_PATH_DOWN)
printf("SEQ4_STATUS_CB_PATH_DOWN ");
if (flags & SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING)
printf("SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING ");
if (flags & SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED)
printf("SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED ");
if (flags & SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED)
printf("SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED ");
if (flags & SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED)
printf("SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED ");
if (flags & SEQ4_STATUS_ADMIN_STATE_REVOKED)
printf("SEQ4_STATUS_ADMIN_STATE_REVOKED ");
if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
printf("SEQ4_STATUS_RECALLABLE_STATE_REVOKED ");
if (flags & SEQ4_STATUS_LEASE_MOVED)
printf("SEQ4_STATUS_LEASE_MOVED ");
if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
printf("SEQ4_STATUS_RESTART_RECLAIM_NEEDED ");
if (flags & SEQ4_STATUS_CB_PATH_DOWN_SESSION)
printf("SEQ4_STATUS_CB_PATH_DOWN_SESSION ");
if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT)
printf("SEQ4_STATUS_BACKCHANNEL_FAULT ");
if (flags & SEQ4_STATUS_DEVID_CHANGED)
printf("SEQ4_STATUS_DEVID_CHANGED ");
if (flags & SEQ4_STATUS_DEVID_DELETED)
printf("SEQ4_STATUS_DEVID_DELETED ");
printf("\n");
}

73
daemon/daemon_debug.h Normal file
View file

@ -0,0 +1,73 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef _DAEMON_DEBUG_
#define _DAEMON_DEBUG_
#ifdef _DEBUG
/* use visual studio's debug heap */
# define _CRTDBG_MAP_ALLOC
# include <stdlib.h>
# include <crtdbg.h>
#else
# include <stdlib.h>
#endif
#define DEFAULT_DEBUG_LEVEL 1
/* daemon_debug.h */
void set_debug_level(int level);
void dprintf(int level, LPCSTR format, ...);
void eprintf(LPCSTR format, ...);
void print_hexbuf(int level, unsigned char *title, unsigned char *buf, int len);
void print_create_attributes(int level, DWORD create_opts);
void print_disposition(int level, DWORD disposition);
void print_access_mask(int level, DWORD access_mask);
void print_share_mode(int level, DWORD mode);
void print_file_id_both_dir_info(int level, FILE_ID_BOTH_DIR_INFO *p);
void print_opcode(int level, DWORD opcode);
const char* opcode2string(DWORD opcode);
const char* nfs_opnum_to_string(int opnum);
const char* nfs_error_string(int status);
void print_condwait_status(int level, int status);
void print_sr_status_flags(int level, int flags);
/* pnfs_debug.c */
enum pnfs_status;
enum pnfs_layout_type;
enum pnfs_iomode;
struct __pnfs_file_layout;
struct __pnfs_file_device;
const char* pnfs_error_string(enum pnfs_status status);
const char* pnfs_layout_type_string(enum pnfs_layout_type type);
const char* pnfs_iomode_string(enum pnfs_iomode iomode);
void dprint_deviceid(int level, const char *title, const unsigned char *deviceid);
void dprint_layout(int level, const struct __pnfs_file_layout *layout);
void dprint_device(int level, const struct __pnfs_file_device *device);
#endif

195
daemon/from_kernel.h Normal file
View file

@ -0,0 +1,195 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef _NFS41_DAEMON_
#define _NFS41_DAEMON_
#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_WRITE_THROUGH 0x00000002
#define FILE_SEQUENTIAL_ONLY 0x00000004
#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_CREATE_TREE_CONNECTION 0x00000080
#define FILE_COMPLETE_IF_OPLOCKED 0x00000100
#define FILE_NO_EA_KNOWLEDGE 0x00000200
#define FILE_OPEN_REMOTE_INSTANCE 0x00000400
#define FILE_RANDOM_ACCESS 0x00000800
#define FILE_DELETE_ON_CLOSE 0x00001000
#define FILE_OPEN_BY_FILE_ID 0x00002000
#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
#define FILE_NO_COMPRESSION 0x00008000
#define FILE_RESERVE_OPFILTER 0x00100000
#define FILE_OPEN_REPARSE_POINT 0x00200000
#define FILE_OPEN_NO_RECALL 0x00400000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
#define FILE_COPY_STRUCTURED_STORAGE 0x00000041
#define FILE_STRUCTURED_STORAGE 0x00000441
#define FILE_SUPERSEDE 0x00000000
#define FILE_OPEN 0x00000001
#define FILE_CREATE 0x00000002
#define FILE_OPEN_IF 0x00000003
#define FILE_OVERWRITE 0x00000004
#define FILE_OVERWRITE_IF 0x00000005
#define FILE_MAXIMUM_DISPOSITION 0x00000005
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation, // 40
FileIoCompletionNotificationInformation, // 41
FileIoStatusBlockRangeInformation, // 42
FileIoPriorityHintInformation, // 43
FileSfioReserveInformation, // 44
FileSfioVolumeInformation, // 45
FileHardLinkInformation, // 46
FileProcessIdsUsingFileInformation, // 47
FileNormalizedNameInformation, // 48
FileNetworkPhysicalNameInformation, // 49
FileIdGlobalTxDirectoryInformation, // 50
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
/* kernel structures for QueryDirectory results */
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
typedef struct _FILE_DIRECTORY_INFO {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_DIRECTORY_INFO, *PFILE_DIRECTORY_INFO;
typedef struct _FILE_BOTH_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
WCHAR ShortName[12];
WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
typedef struct _FILE_FULL_DIR_INFO {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
WCHAR FileName[1];
} FILE_FULL_DIR_INFO, *PFILE_FULL_DIR_INFO;
typedef struct _FILE_ID_FULL_DIR_INFO {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFO, *PFILE_ID_FULL_DIR_INFO;
typedef struct _FILE_LINK_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;
#endif

152
daemon/getattr.c Normal file
View file

@ -0,0 +1,152 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "from_kernel.h"
#include "daemon_debug.h"
#include "nfs41_ops.h"
#include "name_cache.h"
#include "upcall.h"
#include "util.h"
int nfs41_cached_getattr(
IN nfs41_session *session,
IN nfs41_path_fh *file,
OUT nfs41_file_info *info)
{
int status;
/* first look for cached attributes */
status = nfs41_attr_cache_lookup(session_name_cache(session),
file->fh.fileid, info);
if (status) {
/* fetch attributes from the server */
bitmap4 attr_request;
init_getattr_request(&attr_request);
status = nfs41_getattr(session, file, &attr_request, info);
if (status) {
eprintf("nfs41_getattr() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
}
}
return status;
}
int parse_getattr(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
getattr_upcall_args *args = &upcall->args.getattr;
status = safe_read(&buffer, &length, &args->query_class, sizeof(args->query_class));
if (status) goto out;
status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->state, sizeof(args->state));
out:
if (status)
eprintf("parsing NFS41_FILE_QUERY failed with %d\n", status);
else
dprintf(1, "parsing NFS41_FILE_QUERY: info_class=%d buf_len=%d "
"root=0x%p open_state=0x%p\n",
args->query_class, args->buf_len, args->root, args->state);
return status;
}
int handle_getattr(nfs41_upcall *upcall)
{
int status;
getattr_upcall_args *args = &upcall->args.getattr;
nfs41_open_state *state = args->state;
nfs41_file_info info;
ZeroMemory(&info, sizeof(info));
status = nfs41_cached_getattr(state->session, &state->file, &info);
if (status) {
eprintf("nfs41_cached_getattr() failed with %d\n", status);
goto out;
}
switch (args->query_class) {
case FileBasicInformation:
nfs_to_basic_info(&info, &args->basic_info);
break;
case FileStandardInformation:
nfs_to_standard_info(&info, &args->std_info);
break;
case FileAttributeTagInformation:
args->tag_info.FileAttributes = nfs_file_info_to_attributes(&info);
args->tag_info.ReparseTag = 0;
break;
default:
eprintf("unhandled file query class %d\n", args->query_class);
status = ERROR_INVALID_PARAMETER;
break;
}
out:
return status;
}
int marshall_getattr(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
int status;
getattr_upcall_args *args = &upcall->args.getattr;
uint32_t info_len;
switch (args->query_class) {
case FileBasicInformation:
info_len = sizeof(args->basic_info);
status = safe_write(&buffer, length, &info_len, sizeof(info_len));
if (status) goto out;
status = safe_write(&buffer, length, &args->basic_info, info_len);
if (status) goto out;
break;
case FileStandardInformation:
info_len = sizeof(args->std_info);
status = safe_write(&buffer, length, &info_len, sizeof(info_len));
if (status) goto out;
status = safe_write(&buffer, length, &args->std_info, info_len);
if (status) goto out;
break;
case FileAttributeTagInformation:
info_len = sizeof(args->tag_info);
status = safe_write(&buffer, length, &info_len, sizeof(info_len));
if (status) goto out;
status = safe_write(&buffer, length, &args->tag_info, info_len);
if (status) goto out;
break;
default:
eprintf("unknown file query class %d\n", args->query_class);
status = 103;
goto out;
}
out:
return status;
}

116
daemon/list.h Normal file
View file

@ -0,0 +1,116 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef NFS41_LIST_H
#define NFS41_LIST_H
/* doubly-linked list */
struct list_entry {
struct list_entry *prev;
struct list_entry *next;
};
#define list_container(entry, type, field) \
((type*)((const char*)(entry) - (const char*)(&((type*)0)->field)))
#define list_for_each(entry, head) \
for (entry = (head)->next; entry != (head); entry = entry->next)
#define list_for_each_tmp(entry, tmp, head) \
for (entry = (head)->next, tmp = entry->next; entry != (head); \
entry = tmp, tmp = entry->next)
#define list_for_each_reverse(entry, head) \
for (entry = (head)->prev; entry != (head); entry = entry->prev)
#define list_for_each_reverse_tmp(entry, tmp, head) \
for (entry = (head)->next, tmp = entry->next; entry != (head); \
entry = tmp, tmp = entry->next)
static void list_init(
struct list_entry *head)
{
head->prev = head;
head->next = head;
}
static int list_empty(
struct list_entry *head)
{
return head->next == head;
}
static void list_add(
struct list_entry *entry,
struct list_entry *prev,
struct list_entry *next)
{
/* assert(prev->next == next && next->prev == prev); */
entry->prev = prev;
entry->next = next;
prev->next = entry;
next->prev = entry;
}
static void list_add_head(
struct list_entry *head,
struct list_entry *entry)
{
list_add(entry, head, head->next);
}
static void list_add_tail(
struct list_entry *head,
struct list_entry *entry)
{
list_add(entry, head->prev, head);
}
static void list_remove(
struct list_entry *entry)
{
if (!list_empty(entry)) {
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
list_init(entry);
}
}
typedef int (*list_compare_fn)(const struct list_entry*, const void*);
static struct list_entry* list_search(
const struct list_entry *head,
const void *value,
list_compare_fn compare)
{
struct list_entry *entry;
list_for_each(entry, head)
if (compare(entry, value) == 0)
return entry;
return NULL;
}
#endif /* !NFS41_LIST_H */

252
daemon/lock.c Normal file
View file

@ -0,0 +1,252 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "nfs41_ops.h"
#include "upcall.h"
#include "util.h"
#define LKLVL 2 /* dprintf level for lock logging */
stateid4* nfs41_lock_stateid_copy(
IN nfs41_lock_state *lock_state,
IN OUT stateid4 *dest)
{
stateid4 *result;
AcquireSRWLockShared(&lock_state->lock);
if (lock_state->initialized) {
memcpy(dest, &lock_state->stateid, sizeof(stateid4));
result = dest;
dprintf(LKLVL, "nfs41_lock_stateid_copy: copying existing stateid "
"with seqid=%u\n", result->seqid);
} else {
result = NULL;
dprintf(LKLVL, "nfs41_lock_stateid_copy: no existing lock state\n");
}
ReleaseSRWLockShared(&lock_state->lock);
return result;
}
static void update_last_lock_state(
OUT nfs41_lock_state *lock_state,
IN stateid4 *stateid)
{
/* update the lock state if the seqid is more recent */
AcquireSRWLockShared(&lock_state->lock);
if (stateid->seqid > lock_state->stateid.seqid) {
ReleaseSRWLockShared(&lock_state->lock);
AcquireSRWLockExclusive(&lock_state->lock);
if (stateid->seqid > lock_state->stateid.seqid) {
if (lock_state->initialized) {
/* if the lock state already existed, update the seqid only;
* assume that stateid->other remains unchanged */
dprintf(LKLVL, "update_last_lock_state: setting seqid=%u "
"(was %u)\n", stateid->seqid, lock_state->stateid.seqid);
lock_state->stateid.seqid = stateid->seqid;
} else {
/* copy the entire stateid and mark as initialized */
dprintf(LKLVL, "update_last_lock_state: stateid "
"initialized with seqid=%u\n", stateid->seqid);
memcpy(&lock_state->stateid, stateid, sizeof(stateid4));
lock_state->initialized = 1;
}
}
ReleaseSRWLockExclusive(&lock_state->lock);
} else {
dprintf(LKLVL, "update_last_lock_state: discarding seqid=%u "
"(already %u)\n", stateid->seqid, lock_state->stateid.seqid);
ReleaseSRWLockShared(&lock_state->lock);
}
}
/* NFS41_LOCK */
int parse_lock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
lock_upcall_args *args = &upcall->args.lock;
status = safe_read(&buffer, &length, &args->state, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->offset, sizeof(LONGLONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->length, sizeof(LONGLONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->exclusive, sizeof(BOOLEAN));
if (status) goto out;
status = safe_read(&buffer, &length, &args->blocking, sizeof(BOOLEAN));
if (status) goto out;
out:
if (status)
eprintf("parsing NFS41_LOCK failed with %d\n", status);
else
dprintf(1, "parsing NFS41_LOCK: state=%p root=%p offset=0x%llx "
"length=0x%llx exclusive=%u blocking=%u\n",
args->state, args->root, args->offset, args->length,
args->exclusive, args->blocking);
return status;
}
static __inline uint32_t get_lock_type(BOOLEAN exclusive, BOOLEAN blocking)
{
return blocking == 0
? ( exclusive == 0 ? READ_LT : WRITE_LT )
: ( exclusive == 0 ? READW_LT : WRITEW_LT );
}
int handle_lock(nfs41_upcall *upcall)
{
int status;
lock_upcall_args *args = &upcall->args.lock;
nfs41_open_state *state = args->state;
const uint32_t type = get_lock_type(args->exclusive, args->blocking);
stateid4 stateid, *prev_stateid;
prev_stateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
status = nfs41_lock(state->session, state, prev_stateid,
type, args->offset, args->length, &stateid);
if (status) {
dprintf(LKLVL, "nfs41_lock failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
update_last_lock_state(&state->last_lock, &stateid);
out:
return status;
}
int marshall_lock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
return NO_ERROR;
}
int cancel_lock(IN nfs41_upcall *upcall)
{
int status = NO_ERROR;
lock_upcall_args *args = &upcall->args.lock;
nfs41_open_state *state = args->state;
stateid4 stateid, *prev_stateid;
dprintf(1, "--> cancel_lock()\n");
if (upcall->status)
goto out;
prev_stateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
status = nfs41_unlock(state->session, state,
prev_stateid, args->offset, args->length);
if (status) {
dprintf(LKLVL, "cancel_lock: nfs41_unlock() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
update_last_lock_state(&state->last_lock, &stateid);
out:
dprintf(1, "<-- cancel_lock() returning %d\n", status);
return status;
}
/* NFS41_UNLOCK */
int parse_unlock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
unlock_upcall_args *args = &upcall->args.unlock;
status = safe_read(&buffer, &length, &args->state, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->count, sizeof(ULONG));
if (status) goto out;
args->buf = buffer;
args->buf_len = length;
out:
if (status)
eprintf("parsing NFS41_UNLOCK failed with %d\n", status);
else
dprintf(1, "parsing NFS41_UNLOCK: state=%p root=%p count=%u\n",
args->state, args->root, args->count);
return status;
}
int handle_unlock(nfs41_upcall *upcall)
{
int status;
unlock_upcall_args *args = &upcall->args.unlock;
nfs41_open_state *state = args->state;
stateid4 stateid;
uint32_t i, nsuccess = 0;
unsigned char *buf = args->buf;
uint32_t buf_len = args->buf_len;
uint64_t offset;
uint64_t length;
if (nfs41_lock_stateid_copy(&state->last_lock, &stateid) == NULL) {
eprintf("attempt to unlock a file with no lock state\n");
status = ERROR_NOT_LOCKED;
goto out;
}
status = NO_ERROR;
for (i = 0; i < args->count; i++) {
if (safe_read(&buf, &buf_len, &offset, sizeof(LONGLONG))) break;
if (safe_read(&buf, &buf_len, &length, sizeof(LONGLONG))) break;
status = nfs41_unlock(state->session, state, &stateid, offset, length);
if (status == NFS4_OK) {
nsuccess++;
} else {
dprintf(LKLVL, "nfs41_unlock failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
}
}
if (nsuccess) {
update_last_lock_state(&state->last_lock, &stateid);
status = NO_ERROR;
}
out:
return status;
}
int marshall_unlock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
return NO_ERROR;
}

500
daemon/lookup.c Normal file
View file

@ -0,0 +1,500 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include <time.h>
#include "nfs41_compound.h"
#include "nfs41_ops.h"
#include "name_cache.h"
#include "util.h"
#include "daemon_debug.h"
#define LULVL 2 /* dprintf level for lookup logging */
#define MAX_LOOKUP_COMPONENTS 8
/* calculate how much space to allocate for rpc reply */
#define MAX_LOOKUP_RES_SIZE 4
#define MAX_GETFH_RES_SIZE (NFS4_FHSIZE + 8)
#define MAX_GETATTR_RES_SIZE 128 /* depends on what we request */
#define MAX_COMPONENT_RES_SIZE \
(MAX_LOOKUP_RES_SIZE + MAX_GETFH_RES_SIZE + MAX_GETATTR_RES_SIZE)
#define MAX_RPC_RES_SIZE(num_components) \
(MAX_COMPONENT_RES_SIZE * ((num_components) + 1))
/* map NFS4ERR_MOVED to an arbitrary windows error */
#define ERROR_FILESYSTEM_ABSENT ERROR_DEVICE_REMOVED
struct lookup_referral {
nfs41_path_fh parent;
nfs41_component name;
};
typedef struct __nfs41_lookup_component_args {
nfs41_sequence_args sequence;
nfs41_putfh_args putfh;
nfs41_lookup_args lookup[MAX_LOOKUP_COMPONENTS];
nfs41_getattr_args getrootattr;
nfs41_getattr_args getattr[MAX_LOOKUP_COMPONENTS];
bitmap4 attr_request;
} nfs41_lookup_component_args;
typedef struct __nfs41_lookup_component_res {
nfs41_sequence_res sequence;
nfs41_putfh_res putfh;
nfs41_lookup_res lookup[MAX_LOOKUP_COMPONENTS];
nfs41_getfh_res getrootfh;
nfs41_getfh_res getfh[MAX_LOOKUP_COMPONENTS];
nfs41_path_fh root;
nfs41_path_fh file[MAX_LOOKUP_COMPONENTS];
nfs41_getattr_res getrootattr;
nfs41_getattr_res getattr[MAX_LOOKUP_COMPONENTS];
nfs41_file_info rootinfo;
nfs41_file_info info[MAX_LOOKUP_COMPONENTS];
struct lookup_referral *referral;
} nfs41_lookup_component_res;
static void init_component_args(
IN nfs41_lookup_component_args *args,
IN nfs41_lookup_component_res *res,
IN nfs41_abs_path *path,
IN struct lookup_referral *referral)
{
uint32_t i;
ZeroMemory(args, sizeof(nfs41_lookup_component_args));
ZeroMemory(res, sizeof(nfs41_lookup_component_res));
args->attr_request.count = 2;
args->attr_request.arr[0] = FATTR4_WORD0_TYPE
| FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE
| FATTR4_WORD0_FSID | FATTR4_WORD0_FILEID;
args->attr_request.arr[1] = FATTR4_WORD1_MODE
| FATTR4_WORD1_NUMLINKS | FATTR4_WORD1_TIME_ACCESS
| FATTR4_WORD1_TIME_CREATE | FATTR4_WORD1_TIME_MODIFY;
args->getrootattr.attr_request = &args->attr_request;
res->root.path = path;
res->getrootfh.fh = &res->root.fh;
res->getrootattr.info = &res->rootinfo;
res->getrootattr.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
res->referral = referral;
for (i = 0; i < MAX_LOOKUP_COMPONENTS; i++) {
args->getattr[i].attr_request = &args->attr_request;
res->file[i].path = path;
args->lookup[i].name = &res->file[i].name;
res->getfh[i].fh = &res->file[i].fh;
res->getattr[i].info = &res->info[i];
res->getattr[i].obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
}
}
static int lookup_rpc(
IN nfs41_session *session,
IN nfs41_path_fh *dir,
IN uint32_t component_count,
IN nfs41_lookup_component_args *args,
OUT nfs41_lookup_component_res *res)
{
int status;
uint32_t i, buffer_size;
nfs41_compound compound;
nfs_argop4 argops[4+MAX_LOOKUP_COMPONENTS*3];
nfs_resop4 resops[4+MAX_LOOKUP_COMPONENTS*3];
compound_init(&compound, argops, resops);
compound_add_op(&compound, OP_SEQUENCE, &args->sequence, &res->sequence);
status = nfs41_session_sequence(&args->sequence, session, 0);
if (status)
goto out;
if (dir == &res->root) {
compound_add_op(&compound, OP_PUTROOTFH,
NULL, &res->putfh);
compound_add_op(&compound, OP_GETFH,
NULL, &res->getrootfh);
compound_add_op(&compound, OP_GETATTR,
&args->getrootattr, &res->getrootattr);
} else {
args->putfh.file = dir;
compound_add_op(&compound, OP_PUTFH,
&args->putfh, &res->putfh);
}
for (i = 0; i < component_count; i++) {
compound_add_op(&compound, OP_LOOKUP,
&args->lookup[i], &res->lookup[i]);
compound_add_op(&compound, OP_GETFH,
NULL, &res->getfh[i]);
compound_add_op(&compound, OP_GETATTR,
&args->getattr[i], &res->getattr[i]);
}
buffer_size = MAX_RPC_RES_SIZE(component_count);
status = compound_encode_send_decode(session, &compound, 0, buffer_size);
if (status)
goto out;
compound_error(status = compound.res.status);
out:
return status;
}
static int server_lookup(
IN nfs41_session *session,
IN nfs41_path_fh *dir,
IN const char *path,
IN const char *path_end,
IN uint32_t count,
IN nfs41_lookup_component_args *args,
IN nfs41_lookup_component_res *res,
OUT OPTIONAL nfs41_path_fh **parent_out,
OUT OPTIONAL nfs41_path_fh **target_out,
OUT OPTIONAL nfs41_file_info *info_out)
{
nfs41_path_fh *file, *parent;
uint32_t i = 0;
int status;
if (parent_out) *parent_out = NULL;
if (target_out) *target_out = NULL;
lookup_rpc(session, dir, count, args, res);
status = res->sequence.sr_status; if (status) goto out;
status = res->putfh.status; if (status) goto out;
status = res->getrootfh.status; if (status) goto out;
status = res->getrootattr.status; if (status) goto out;
if (dir == &res->root) {
nfs41_component name = { 0 };
/* fill in the file handle's fileid and superblock */
dir->fh.fileid = res->getrootattr.info->fileid;
status = nfs41_superblock_for_fh(session,
&res->getrootattr.info->fsid, NULL, dir);
if (status)
goto out;
/* get the name of the parent (empty if its the root) */
last_component(path, count ? args->lookup[0].name->name : path_end, &name);
/* add the file handle and attributes to the name cache */
memcpy(&res->getrootattr.info->attrmask,
&res->getrootattr.obj_attributes.attrmask, sizeof(bitmap4));
nfs41_name_cache_insert(session_name_cache(session),
path, &name, &dir->fh, res->getrootattr.info, NULL);
}
file = dir;
if (count == 0) {
if (target_out)
*target_out = dir;
if (info_out)
memcpy(info_out, res->getrootattr.info, sizeof(nfs41_file_info));
} else if (count == 1) {
if (parent_out)
*parent_out = dir;
}
for (i = 0; i < count; i++) {
status = res->lookup[i].status; if (status) break;
if (res->getfh[i].status == NFS4ERR_MOVED) {
/* save enough information to follow the referral */
path_fh_copy(&res->referral->parent, file);
res->referral->name.name = args->lookup[i].name->name;
res->referral->name.len = args->lookup[i].name->len;
return ERROR_FILESYSTEM_ABSENT;
}
status = res->getfh[i].status; if (status) break;
status = res->getattr[i].status; if (status) break;
parent = file;
file = &res->file[i];
/* fill in the file handle's fileid and superblock */
file->fh.fileid = res->getattr[i].info->fileid;
status = nfs41_superblock_for_fh(session,
&res->getattr[i].info->fsid, &parent->fh, file);
if (status)
break;
/* add the file handle and attributes to the name cache */
memcpy(&res->getattr[i].info->attrmask,
&res->getattr[i].obj_attributes.attrmask, sizeof(bitmap4));
nfs41_name_cache_insert(session_name_cache(session),
path, args->lookup[i].name, &res->file[i].fh,
res->getattr[i].info, NULL);
if (i == count-1) {
if (target_out)
*target_out = file;
if (info_out)
memcpy(info_out, res->getattr[i].info, sizeof(nfs41_file_info));
} else if (i == count-2) {
if (parent_out)
*parent_out = file;
}
}
out:
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
/* use PATH_NOT_FOUND for all but the last name */
if (status == ERROR_FILE_NOT_FOUND && i != count-1)
status = ERROR_PATH_NOT_FOUND;
return status;
}
static uint32_t max_lookup_components(
IN const nfs41_session *session)
{
const uint32_t comps = (session->fore_chan_attrs.ca_maxoperations - 4) / 3;
return min(comps, MAX_LOOKUP_COMPONENTS);
}
static uint32_t get_component_array(
IN OUT const char **path_pos,
IN const char *path_end,
IN uint32_t max_components,
OUT nfs41_path_fh *components,
OUT uint32_t *component_count)
{
uint32_t i;
for (i = 0; i < max_components; i++) {
if (!next_component(*path_pos, path_end, &components[i].name))
break;
*path_pos = components[i].name.name + components[i].name.len;
}
*component_count = i;
return i;
}
static int server_lookup_loop(
IN nfs41_session *session,
IN OPTIONAL nfs41_path_fh *parent_in,
IN nfs41_abs_path *path,
IN const char *path_pos,
IN struct lookup_referral *referral,
OUT OPTIONAL nfs41_path_fh *parent_out,
OUT OPTIONAL nfs41_path_fh *target_out,
OUT OPTIONAL nfs41_file_info *info_out)
{
nfs41_lookup_component_args args;
nfs41_lookup_component_res res;
nfs41_path_fh *dir, *parent, *target;
const char *path_end;
const uint32_t max_components = max_lookup_components(session);
uint32_t count;
int status = NO_ERROR;
init_component_args(&args, &res, path, referral);
parent = NULL;
target = NULL;
path_end = path->path + path->len;
dir = parent_in ? parent_in : &res.root;
while (get_component_array(&path_pos, path_end,
max_components, res.file, &count)) {
status = server_lookup(session, dir, path->path, path_end, count,
&args, &res, &parent, &target, info_out);
if (status == ERROR_FILE_NOT_FOUND && is_last_component(path_pos, path_end))
goto out_parent;
if (status)
goto out;
dir = target;
}
if (dir == &res.root && (target_out || info_out)) {
/* didn't get any components, so we just need the root */
status = server_lookup(session, dir, path->path, path_end,
0, &args, &res, &parent, &target, info_out);
if (status)
goto out;
}
if (target_out && target) fh_copy(&target_out->fh, &target->fh);
out_parent:
if (parent_out && parent) fh_copy(&parent_out->fh, &parent->fh);
out:
return status;
}
static void referral_locations_free(
IN fs_locations4 *locations)
{
uint32_t i;
if (locations->locations) {
for (i = 0; i < locations->location_count; i++)
free(locations->locations[i].servers);
free(locations->locations);
}
}
static int referral_resolve(
IN nfs41_root *root,
IN nfs41_session *session_in,
IN struct lookup_referral *referral,
OUT nfs41_abs_path *path_out,
OUT nfs41_session **session_out)
{
char rest_of_path[NFS41_MAX_PATH_LEN];
fs_locations4 locations = { 0 };
const fs_location4 *location;
nfs41_client *client;
int status;
/* get fs_locations */
status = nfs41_fs_locations(session_in, &referral->parent,
&referral->name, &locations);
if (status) {
eprintf("nfs41_fs_locations() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_PATH_NOT_FOUND);
goto out;
}
/* mount the first location available */
status = nfs41_root_mount_referral(root, &locations, &location, &client);
if (status) {
eprintf("nfs41_root_mount_referral() failed with %d\n",
status);
goto out;
}
/* format a new path from that location's root */
StringCchCopyA(rest_of_path, NFS41_MAX_PATH_LEN,
referral->name.name + referral->name.len);
AcquireSRWLockExclusive(&path_out->lock);
abs_path_copy(path_out, &location->path);
StringCchCatA(path_out->path, NFS41_MAX_PATH_LEN, rest_of_path);
path_out->len += (unsigned short)strlen(rest_of_path);
ReleaseSRWLockExclusive(&path_out->lock);
if (session_out) *session_out = client->session;
out:
referral_locations_free(&locations);
return status;
}
int nfs41_lookup(
IN nfs41_root *root,
IN nfs41_session *session,
IN OUT nfs41_abs_path *path_inout,
OUT OPTIONAL nfs41_path_fh *parent_out,
OUT OPTIONAL nfs41_path_fh *target_out,
OUT OPTIONAL nfs41_file_info *info_out,
OUT nfs41_session **session_out)
{
nfs41_abs_path path;
struct nfs41_name_cache *cache = session_name_cache(session);
nfs41_path_fh parent, target, *server_start;
const char *path_pos, *path_end;
struct lookup_referral referral;
int status;
if (session_out) *session_out = session;
InitializeSRWLock(&path.lock);
/* to avoid holding this lock over multiple rpcs,
* make a copy of the path and use that instead */
AcquireSRWLockShared(&path_inout->lock);
abs_path_copy(&path, path_inout);
ReleaseSRWLockShared(&path_inout->lock);
path_pos = path.path;
path_end = path.path + path.len;
dprintf(LULVL, "--> nfs41_lookup('%s')\n", path.path);
if (parent_out == NULL) parent_out = &parent;
if (target_out == NULL) target_out = &target;
parent_out->fh.len = target_out->fh.len = 0;
status = nfs41_name_cache_lookup(cache,
path_pos, path_end, &path_pos,
&parent_out->fh, &target_out->fh, info_out);
if (status == NO_ERROR)
goto out;
if (target_out->fh.len) {
/* start where the name cache left off */
if (target_out != &target) {
/* must make a copy for server_start, because
* server_lookup_loop() will overwrite target_out */
path_fh_copy(&target, target_out);
}
server_start = &target;
} else {
/* start with PUTROOTFH */
server_start = NULL;
}
status = server_lookup_loop(session, server_start,
&path, path_pos, &referral, parent_out, target_out, info_out);
if (status == ERROR_FILESYSTEM_ABSENT) {
nfs41_session *new_session;
/* create a session to the referred server and
* reformat the path relative to that server's root */
status = referral_resolve(root, session,
&referral, path_inout, &new_session);
if (status) {
eprintf("referral_resolve() failed with %d\n", status);
goto out;
}
/* update the positions of the parent and target components */
last_component(path_inout->path, path_inout->path + path_inout->len,
&target_out->name);
last_component(path_inout->path, target_out->name.name,
&parent_out->name);
if (session_out) *session_out = new_session;
/* look up the new path */
status = nfs41_lookup(root, new_session, path_inout,
parent_out, target_out, info_out, session_out);
}
out:
dprintf(LULVL, "<-- nfs41_lookup() returning %d\n", status);
return status;
}

8
daemon/makefile Normal file
View file

@ -0,0 +1,8 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

131
daemon/mount.c Normal file
View file

@ -0,0 +1,131 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "nfs41_ops.h"
#include "upcall.h"
#include "util.h"
/* NFS41_MOUNT */
int parse_mount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
mount_upcall_args *args = &upcall->args.mount;
status = get_name(&buffer, &length, args->srv_name);
if(status) goto out;
ZeroMemory(&args->path, sizeof(nfs41_abs_path));
status = get_abs_path(&buffer, &length, &args->path);
out:
if (status)
eprintf("parsing of NFS41_MOUNT failed with %d\n", status);
else
dprintf(1, "parsing NFS14_MOUNT: srv_name=%s root=%s\n",
args->srv_name, args->path.path);
return status;
}
int handle_mount(nfs41_upcall *upcall)
{
int status;
mount_upcall_args *args = &upcall->args.mount;
multi_addr4 addrs;
const unsigned short port = 2049;
nfs41_root *root;
nfs41_client *client;
// resolve hostname,port
status = nfs41_server_resolve(args->srv_name, port, &addrs);
if (status) {
eprintf("nfs41_server_resolve() failed with %d\n", status);
goto out;
}
// create root
status = nfs41_root_create(args->srv_name, port, &args->path,
NFS41_MAX_FILEIO_SIZE + WRITE_OVERHEAD,
NFS41_MAX_FILEIO_SIZE + READ_OVERHEAD, &root);
if (status) {
eprintf("nfs41_rpc_clnt_create failed %d\n", status);
goto out;
}
// add a mount
status = nfs41_root_mount_addrs(root, &addrs, 0, 0, &client);
if (status) {
eprintf("nfs41_root_mount() failed with %d\n", status);
goto out_err;
}
// look up the mount path, and fail if it doesn't exist
status = nfs41_lookup(root, client->session,
&args->path, NULL, NULL, NULL, NULL);
if (status) {
eprintf("nfs41_lookup('%s') failed with %d\n",
args->path.path, status);
goto out_err;
}
args->root = root;
out:
return status;
out_err:
nfs41_root_free(root);
goto out;
}
int marshall_mount(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
mount_upcall_args *args = &upcall->args.mount;
dprintf(2, "NFS41_MOUNT: writing pointer to nfs41_root %p\n", args->root);
return safe_write(&buffer, length, &args->root, sizeof(args->root));
}
/* NFS41_UNMOUNT */
int parse_unmount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
unmount_upcall_args *args = &upcall->args.unmount;
status = safe_read(&buffer, &length, &args->root, sizeof(nfs41_session *));
if (status)
eprintf("parsing NFS41_UNMOUNT failed with %d\n", status);
else
dprintf(1, "parsing NFS41_UNMOUNT: unmount root=%p\n", args->root);
return status;
}
int handle_unmount(nfs41_upcall *upcall)
{
int status = NO_ERROR;
unmount_upcall_args *args = &upcall->args.unmount;
nfs41_root_free(args->root);
return status;
}
int marshall_unmount(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
return NO_ERROR;
}

1243
daemon/name_cache.c Normal file

File diff suppressed because it is too large Load diff

99
daemon/name_cache.h Normal file
View file

@ -0,0 +1,99 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_DAEMON_NAME_CACHE_H__
#define __NFS41_DAEMON_NAME_CACHE_H__
#include "nfs41.h"
static __inline struct nfs41_name_cache* client_name_cache(
IN nfs41_client *client)
{
return client_server(client)->name_cache;
}
static __inline struct nfs41_name_cache* session_name_cache(
IN nfs41_session *session)
{
return client_name_cache(session->client);
}
/* attribute cache */
int nfs41_attr_cache_lookup(
IN struct nfs41_name_cache *cache,
IN uint64_t fileid,
OUT nfs41_file_info *info_out);
int nfs41_attr_cache_update(
IN struct nfs41_name_cache *cache,
IN uint64_t fileid,
IN const nfs41_file_info *info);
/* name cache */
int nfs41_name_cache_create(
OUT struct nfs41_name_cache **cache_out);
int nfs41_name_cache_free(
IN OUT struct nfs41_name_cache **cache_out);
int nfs41_name_cache_lookup(
IN struct nfs41_name_cache *cache,
IN const char *path,
IN const char *path_end,
OUT OPTIONAL const char **remaining_path_out,
OUT OPTIONAL nfs41_fh *parent_out,
OUT OPTIONAL nfs41_fh *target_out,
OUT OPTIONAL nfs41_file_info *info_out);
int nfs41_name_cache_insert(
IN struct nfs41_name_cache *cache,
IN const char *path,
IN const nfs41_component *name,
IN const nfs41_fh *fh,
IN const nfs41_file_info *info,
IN OPTIONAL const change_info4 *cinfo);
int nfs41_name_cache_remove(
IN struct nfs41_name_cache *cache,
IN const char *path,
IN const nfs41_component *name,
IN const change_info4 *cinfo);
int nfs41_name_cache_rename(
IN struct nfs41_name_cache *cache,
IN const char *src_path,
IN const nfs41_component *src_name,
IN const change_info4 *src_cinfo,
IN const char *dst_path,
IN const nfs41_component *dst_name,
IN const change_info4 *dst_cinfo);
int nfs41_name_cache_remove_stale(
IN struct nfs41_name_cache *cache,
IN nfs41_session *session,
IN nfs41_abs_path *path);
#endif /* !__NFS41_DAEMON_NAME_CACHE_H__ */

458
daemon/namespace.c Normal file
View file

@ -0,0 +1,458 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include "nfs41_ops.h"
#include "util.h"
#include "daemon_debug.h"
#define NSLVL 2 /* dprintf level for namespace logging */
#define client_entry(pos) list_container(pos, nfs41_client, root_entry)
/* nfs41_root */
int nfs41_root_create(
IN const char *hostname,
IN unsigned short port,
IN const nfs41_abs_path *path,
IN uint32_t wsize,
IN uint32_t rsize,
OUT nfs41_root **root_out)
{
int status = NO_ERROR;
nfs41_root *root;
dprintf(NSLVL, "--> nfs41_root_create(%s:%u:%s)\n",
hostname, port, path);
root = calloc(1, sizeof(nfs41_root));
if (root == NULL) {
status = GetLastError();
goto out;
}
list_init(&root->clients);
root->port = port;
root->wsize = wsize;
root->rsize = rsize;
InitializeCriticalSection(&root->lock);
/* generate a unique client_owner */
status = nfs41_client_owner(&root->client_owner);
if (status) {
eprintf("nfs41_client_owner() failed with %d\n", status);
goto out;
}
*root_out = root;
out:
dprintf(NSLVL, "<-- nfs41_root_create() returning %d\n", status);
return status;
}
void nfs41_root_free(
IN nfs41_root *root)
{
struct list_entry *entry, *tmp;
dprintf(NSLVL, "--> nfs41_root_free()\n");
/* free clients */
list_for_each_tmp(entry, tmp, &root->clients)
nfs41_client_free(client_entry(entry));
free(root);
dprintf(NSLVL, "<-- nfs41_root_free()\n");
}
/* root_client_find_addrs() */
struct cl_addr_info {
const multi_addr4 *addrs;
uint32_t roles;
};
static int cl_addr_compare(
IN const struct list_entry *entry,
IN const void *value)
{
nfs41_client *client = client_entry(entry);
const struct cl_addr_info *info = (const struct cl_addr_info*)value;
uint32_t i, roles;
/* match any of the desired roles */
AcquireSRWLockShared(&client->exid_lock);
roles = info->roles & client->roles;
ReleaseSRWLockShared(&client->exid_lock);
if (roles == 0)
return ERROR_FILE_NOT_FOUND;
/* match any address in 'addrs' with any address in client->rpc->addrs */
for (i = 0; i < info->addrs->count; i++)
if (multi_addr_find(&client->rpc->addrs, &info->addrs->arr[i], NULL))
return NO_ERROR;
return ERROR_FILE_NOT_FOUND;
}
static int root_client_find_addrs(
IN nfs41_root *root,
IN const multi_addr4 *addrs,
IN bool_t is_data,
OUT nfs41_client **client_out)
{
struct cl_addr_info info;
struct list_entry *entry;
int status;
dprintf(NSLVL, "--> root_client_find_addrs()\n");
info.addrs = addrs;
info.roles = nfs41_exchange_id_flags(is_data) & EXCHGID4_FLAG_MASK_PNFS;
entry = list_search(&root->clients, &info, cl_addr_compare);
if (entry) {
*client_out = client_entry(entry);
status = NO_ERROR;
dprintf(NSLVL, "<-- root_client_find_addrs() returning 0x%p\n",
*client_out);
} else {
status = ERROR_FILE_NOT_FOUND;
dprintf(NSLVL, "<-- root_client_find_addrs() failed with %d\n",
status);
}
return status;
}
/* root_client_find() */
struct cl_exid_info {
const nfs41_exchange_id_res *exchangeid;
uint32_t roles;
};
static int cl_exid_compare(
IN const struct list_entry *entry,
IN const void *value)
{
nfs41_client *client = client_entry(entry);
const struct cl_exid_info *info = (const struct cl_exid_info*)value;
int status = ERROR_FILE_NOT_FOUND;
AcquireSRWLockShared(&client->exid_lock);
/* match any of the desired roles */
if ((info->roles & client->roles) == 0)
goto out;
/* match clientid */
if (info->exchangeid->clientid != client->clnt_id)
goto out;
/* match server_owner.major_id */
if (strncmp(info->exchangeid->server_owner.so_major_id,
client->server->owner, NFS4_OPAQUE_LIMIT) != 0)
goto out;
/* match server_scope */
if (strncmp(info->exchangeid->server_scope,
client->server->scope, NFS4_OPAQUE_LIMIT) != 0)
goto out;
status = NO_ERROR;
out:
ReleaseSRWLockShared(&client->exid_lock);
return status;
}
static int root_client_find(
IN nfs41_root *root,
IN const nfs41_exchange_id_res *exchangeid,
IN bool_t is_data,
OUT nfs41_client **client_out)
{
struct cl_exid_info info;
struct list_entry *entry;
int status;
dprintf(NSLVL, "--> root_client_find()\n");
info.exchangeid = exchangeid;
info.roles = nfs41_exchange_id_flags(is_data) & EXCHGID4_FLAG_MASK_PNFS;
entry = list_search(&root->clients, &info, cl_exid_compare);
if (entry) {
*client_out = client_entry(entry);
status = NO_ERROR;
dprintf(NSLVL, "<-- root_client_find() returning 0x%p\n",
*client_out);
} else {
status = ERROR_FILE_NOT_FOUND;
dprintf(NSLVL, "<-- root_client_find() failed with %d\n",
status);
}
return status;
}
static int session_get_lease(
IN nfs41_session *session,
IN OPTIONAL uint32_t lease_time)
{
bool_t use_mds_lease;
int status;
/* http://tools.ietf.org/html/rfc5661#section-13.1.1
* 13.1.1. Sessions Considerations for Data Servers:
* If the reply to EXCHANGE_ID has just the EXCHGID4_FLAG_USE_PNFS_DS role
* set, then (as noted in Section 13.6) the client will not be able to
* determine the data server's lease_time attribute because GETATTR will
* not be permitted. Instead, the rule is that any time a client
* receives a layout referring it to a data server that returns just the
* EXCHGID4_FLAG_USE_PNFS_DS role, the client MAY assume that the
* lease_time attribute from the metadata server that returned the
* layout applies to the data server. */
AcquireSRWLockShared(&session->client->exid_lock);
use_mds_lease = session->client->roles == EXCHGID4_FLAG_USE_PNFS_DS;
ReleaseSRWLockShared(&session->client->exid_lock);
if (!use_mds_lease) {
/* the client is allowed to GETATTR, so query the lease_time */
nfs41_file_info info = { 0 };
bitmap4 attr_request = { 1, { FATTR4_WORD0_LEASE_TIME, 0, 0 } };
status = nfs41_getattr(session, NULL, &attr_request, &info);
if (status) {
eprintf("nfs41_getattr() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
lease_time = info.lease_time;
}
status = nfs41_session_set_lease(session, lease_time);
if (status) {
eprintf("nfs41_session_set_lease() failed %d\n", status);
goto out;
}
out:
return status;
}
static int root_client_create(
IN nfs41_root *root,
IN nfs41_rpc_clnt *rpc,
IN bool_t is_data,
IN OPTIONAL uint32_t lease_time,
IN const nfs41_exchange_id_res *exchangeid,
OUT nfs41_client **client_out)
{
nfs41_client *client;
nfs41_session *session;
int status;
/* create client (transfers ownership of rpc to client) */
status = nfs41_client_create(rpc, &root->client_owner,
is_data, exchangeid, &client);
if (status) {
eprintf("nfs41_client_create() failed with %d\n", status);
goto out;
}
rpc->client = client;
/* create session (and client takes ownership) */
status = nfs41_session_create(client, &session);
if (status) {
eprintf("nfs41_session_create failed %d\n", status);
goto out_err;
}
if (!is_data) {
/* send RECLAIM_COMPLETE, but don't fail on ERR_NOTSUPP */
status = nfs41_reclaim_complete(session);
if (status && status != NFS4ERR_NOTSUPP) {
eprintf("nfs41_reclaim_complete() failed with %s\n",
nfs_error_string(status));
status = ERROR_BAD_NETPATH;
goto out_err;
}
}
/* get least time and start session renewal thread */
status = session_get_lease(session, lease_time);
if (status)
goto out_err;
*client_out = client;
out:
return status;
out_err:
nfs41_client_free(client);
goto out;
}
int nfs41_root_mount_addrs(
IN nfs41_root *root,
IN const multi_addr4 *addrs,
IN bool_t is_data,
IN OPTIONAL uint32_t lease_time,
OUT nfs41_client **client_out)
{
nfs41_exchange_id_res exchangeid;
nfs41_rpc_clnt *rpc;
nfs41_client *client, *existing;
int status;
dprintf(NSLVL, "--> nfs41_root_mount_addrs()\n");
/* look for an existing client that matches the address and role */
EnterCriticalSection(&root->lock);
status = root_client_find_addrs(root, addrs, is_data, &client);
LeaveCriticalSection(&root->lock);
if (status == NO_ERROR)
goto out;
/* create an rpc client */
status = nfs41_rpc_clnt_create(addrs, root->wsize, root->rsize, !is_data, &rpc);
if (status) {
eprintf("nfs41_rpc_clnt_create() failed %d\n", status);
goto out;
}
/* get a clientid with exchangeid */
ZeroMemory(&exchangeid, sizeof(exchangeid));
status = nfs41_exchange_id(rpc, &root->client_owner,
nfs41_exchange_id_flags(is_data), &exchangeid);
if (status) {
eprintf("nfs41_exchange_id() failed %s\n",
nfs_error_string(status));
status = ERROR_BAD_NET_RESP;
goto out_free_rpc;
}
/* attempt to match existing clients by the exchangeid response */
EnterCriticalSection(&root->lock);
status = root_client_find(root, &exchangeid, is_data, &client);
LeaveCriticalSection(&root->lock);
if (status == NO_ERROR)
goto out_free_rpc;
/* create a client for this clientid */
status = root_client_create(root, rpc, is_data,
lease_time, &exchangeid, &client);
if (status) {
eprintf("nfs41_client_create() failed %d\n", status);
goto out;
}
/* because we don't hold the root's lock over session creation,
* we could end up creating multiple clients with the same
* server and roles */
EnterCriticalSection(&root->lock);
status = root_client_find(root, &exchangeid, is_data, &existing);
if (status) {
dprintf(NSLVL, "caching new client 0x%p\n", client);
/* the client is not a duplicate, so add it to the list */
list_add_tail(&root->clients, &client->root_entry);
status = NO_ERROR;
} else {
dprintf(NSLVL, "created a duplicate client 0x%p! using "
"existing client 0x%p instead\n", client, existing);
/* a matching client has been created in parallel, so free
* the one we created and use the existing client instead */
nfs41_client_free(client);
client = existing;
}
LeaveCriticalSection(&root->lock);
out:
if (status == NO_ERROR)
*client_out = client;
dprintf(NSLVL, "<-- nfs41_root_mount_addrs() returning %d\n", status);
return status;
out_free_rpc:
nfs41_rpc_clnt_free(rpc);
goto out;
}
/* http://tools.ietf.org/html/rfc5661#section-11.9
* 11.9. The Attribute fs_locations
* An entry in the server array is a UTF-8 string and represents one of a
* traditional DNS host name, IPv4 address, IPv6 address, or a zero-length
* string. An IPv4 or IPv6 address is represented as a universal address
* (see Section 3.3.9 and [15]), minus the netid, and either with or without
* the trailing ".p1.p2" suffix that represents the port number. If the
* suffix is omitted, then the default port, 2049, SHOULD be assumed. A
* zero-length string SHOULD be used to indicate the current address being
* used for the RPC call. */
static int referral_mount_location(
IN nfs41_root *root,
IN const fs_location4 *loc,
OUT nfs41_client **client_out)
{
multi_addr4 addrs;
int status = ERROR_BAD_NET_NAME;
uint32_t i;
/* create a client and session for the first available server */
for (i = 0; i < loc->server_count; i++) {
/* XXX: only deals with 'address' as a hostname with default port */
status = nfs41_server_resolve(loc->servers[i].address, 2049, &addrs);
if (status) continue;
status = nfs41_root_mount_addrs(root, &addrs, 0, 0, client_out);
if (status == NO_ERROR)
break;
}
return status;
}
int nfs41_root_mount_referral(
IN nfs41_root *root,
IN const fs_locations4 *locations,
OUT const fs_location4 **loc_out,
OUT nfs41_client **client_out)
{
int status = ERROR_BAD_NET_NAME;
uint32_t i;
/* establish a mount to the first available location */
for (i = 0; i < locations->location_count; i++) {
status = referral_mount_location(root,
&locations->locations[i], client_out);
if (status == NO_ERROR) {
*loc_out = &locations->locations[i];
break;
}
}
return status;
}

357
daemon/nfs41.h Normal file
View file

@ -0,0 +1,357 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41__
#define __NFS41__
#include "nfs41_types.h"
#include "list.h"
struct __nfs41_session;
struct __nfs41_client;
struct __rpc_client;
typedef struct __nfs41_superblock {
nfs41_fsid fsid;
bitmap4 supported_attrs;
uint64_t maxread;
uint64_t maxwrite;
uint32_t layout_types;
struct list_entry entry; /* position in nfs41_server.superblocks */
SRWLOCK lock;
} nfs41_superblock;
typedef struct __nfs41_superblock_list {
struct list_entry head;
SRWLOCK lock;
} nfs41_superblock_list;
struct server_addrs {
multi_addr4 addrs; /* list of addrs we've used with this server */
uint32_t next_index;
SRWLOCK lock;
};
typedef struct __nfs41_server {
char scope[NFS4_OPAQUE_LIMIT]; /* server_scope from exchangeid */
char owner[NFS4_OPAQUE_LIMIT]; /* server_owner.major_id from exchangeid */
struct server_addrs addrs;
nfs41_superblock_list superblocks;
struct nfs41_name_cache *name_cache;
struct list_entry entry; /* position in global server list */
LONG ref_count;
} nfs41_server;
typedef struct __nfs41_lock_state {
bool_t initialized;
stateid4 stateid;
SRWLOCK lock;
} nfs41_lock_state;
typedef struct __nfs41_open_state {
nfs41_abs_path path;
nfs41_path_fh parent;
nfs41_path_fh file;
struct __nfs41_session *session;
uint32_t type;
bool_t do_close;
stateid4 stateid;
state_owner4 owner;
nfs41_lock_state last_lock;
struct __pnfs_file_layout *layout;
SRWLOCK lock;
} nfs41_open_state;
typedef struct __nfs41_rpc_clnt {
struct __rpc_client *rpc;
SRWLOCK lock;
HANDLE cond;
struct __nfs41_client *client;
multi_addr4 addrs;
uint32_t addr_index; /* index of addr we're using */
uint32_t wsize;
uint32_t rsize;
uint32_t version;
bool_t is_valid_session;
bool_t in_recovery;
} nfs41_rpc_clnt;
typedef struct __nfs41_client {
nfs41_server *server;
client_owner4 owner;
uint64_t clnt_id;
uint32_t seq_id;
uint32_t roles;
SRWLOCK exid_lock;
struct __nfs41_session *session;
SRWLOCK session_lock;
nfs41_rpc_clnt *rpc;
bool_t is_data;
struct pnfs_file_layout_list *layouts;
struct pnfs_file_device_list *devices;
struct list_entry root_entry; /* position in nfs41_root.clients */
HANDLE cond;
bool_t in_recovery;
} nfs41_client;
#define NFS41_MAX_NUM_SLOTS NFS41_MAX_RPC_REQS
typedef struct __nfs41_slot_table {
uint32_t seq_nums[NFS41_MAX_NUM_SLOTS];
uint32_t used_slots[NFS41_MAX_NUM_SLOTS];
uint32_t max_slots;
uint32_t highest_used;
HANDLE lock;
HANDLE cond;
} nfs41_slot_table;
typedef struct __nfs41_channel_attrs {
uint32_t ca_headerpadsize;
uint32_t ca_maxrequestsize;
uint32_t ca_maxresponsesize;
uint32_t ca_maxresponsesize_cached;
uint32_t ca_maxoperations;
uint32_t ca_maxrequests;
uint32_t *ca_rdma_ird;
} nfs41_channel_attrs;
typedef struct __nfs41_cb_session {
unsigned char cb_sessionid[NFS4_SESSIONID_SIZE];
uint32_t cb_seqnum;
uint32_t cb_slotid;
bool_t cb_is_valid_state;
bool_t cb_cache_this;
} nfs41_cb_session;
typedef struct __nfs41_session {
nfs41_client *client;
unsigned char session_id[NFS4_SESSIONID_SIZE];
nfs41_channel_attrs fore_chan_attrs;
nfs41_channel_attrs back_chan_attrs;
uint32_t lease_time;
nfs41_slot_table table;
// array of slots
HANDLE renew_thread;
bool_t isValidState;
uint32_t flags;
nfs41_cb_session cb_session;
} nfs41_session;
typedef struct __nfs41_root {
client_owner4 client_owner;
CRITICAL_SECTION lock;
struct list_entry clients;
uint32_t wsize;
uint32_t rsize;
unsigned short port;
} nfs41_root;
/* nfs41_namespace.c */
int nfs41_root_create(
IN const char *hostname,
IN unsigned short port,
IN const nfs41_abs_path *path,
IN uint32_t wsize,
IN uint32_t rsize,
OUT nfs41_root **root_out);
void nfs41_root_free(
IN nfs41_root *root);
int nfs41_root_mount_addrs(
IN nfs41_root *root,
IN const multi_addr4 *addrs,
IN bool_t is_data,
IN OPTIONAL uint32_t lease_time,
OUT nfs41_client **client_out);
int nfs41_root_mount_server(
IN nfs41_root *root,
IN nfs41_server *server,
IN bool_t is_data,
IN OPTIONAL uint32_t lease_time,
OUT nfs41_client **client_out);
int nfs41_root_mount_referral(
IN nfs41_root *root,
IN const fs_locations4 *locations,
OUT const fs_location4 **loc_out,
OUT nfs41_client **client_out);
static __inline nfs41_session* nfs41_root_session(
IN nfs41_root *root)
{
nfs41_client *client;
/* return a session for the server at the root of the namespace.
* because we created it on mount, it's the first one in the list */
EnterCriticalSection(&root->lock);
client = list_container(root->clients.next, nfs41_client, root_entry);
LeaveCriticalSection(&root->lock);
return client->session;
}
/* nfs41_session.c */
int nfs41_session_create(
IN nfs41_client *client,
IN nfs41_session **session_out);
int nfs41_session_renew(
IN nfs41_session *session);
int nfs41_session_set_lease(
IN nfs41_session *session,
IN uint32_t lease_time);
void nfs41_session_free(
IN nfs41_session *session);
int nfs41_session_bump_seq(
IN nfs41_session *session,
IN uint32_t slotid);
int nfs41_session_free_slot(
IN nfs41_session *session,
IN uint32_t slotid);
int nfs41_session_get_slot(
IN nfs41_session *session,
OUT uint32_t *slot,
OUT uint32_t *seq,
OUT uint32_t *highest);
struct __nfs41_sequence_args;
int nfs41_session_sequence(
struct __nfs41_sequence_args *args,
nfs41_session *session,
bool_t cachethis);
/* nfs41_server.c */
void nfs41_server_list_init();
int nfs41_server_resolve(
IN const char *hostname,
IN unsigned short port,
OUT multi_addr4 *addrs);
int nfs41_server_find_or_create(
IN const char *server_owner_major_id,
IN const char *server_scope,
IN const netaddr4 *addr,
OUT nfs41_server **server_out);
void nfs41_server_ref(
IN nfs41_server *server);
void nfs41_server_deref(
IN nfs41_server *server);
void nfs41_server_addrs(
IN nfs41_server *server,
OUT multi_addr4 *addrs);
/* nfs41_client.c */
int nfs41_client_owner(
OUT client_owner4 *owner);
uint32_t nfs41_exchange_id_flags(
IN bool_t is_data);
struct __nfs41_exchange_id_res;
int nfs41_client_create(
IN nfs41_rpc_clnt *rpc,
IN const client_owner4 *owner,
IN bool_t is_data,
IN const struct __nfs41_exchange_id_res *exchangeid,
OUT nfs41_client **client_out);
int nfs41_client_renew(
IN nfs41_client *client);
void nfs41_client_free(
IN nfs41_client *client);
static __inline nfs41_server* client_server(
IN nfs41_client *client)
{
/* the client's server could change during nfs41_client_renew(),
* so access to client->server must be protected */
nfs41_server *server;
AcquireSRWLockShared(&client->exid_lock);
server = client->server;
ReleaseSRWLockShared(&client->exid_lock);
return server;
}
/* nfs41_superblock.c */
int nfs41_superblock_for_fh(
IN nfs41_session *session,
IN const nfs41_fsid *fsid,
IN const nfs41_fh *parent OPTIONAL,
OUT nfs41_path_fh *file);
void nfs41_superblock_list_init(
IN nfs41_superblock_list *superblocks);
void nfs41_superblock_list_free(
IN nfs41_superblock_list *superblocks);
/* nfs41_rpc.c */
int nfs41_rpc_clnt_create(
IN const multi_addr4 *addrs,
IN uint32_t wsize,
IN uint32_t rsize,
IN bool_t needcb,
OUT nfs41_rpc_clnt **rpc_out);
void nfs41_rpc_clnt_free(
IN nfs41_rpc_clnt *rpc);
int nfs41_send_compound(
IN nfs41_rpc_clnt *rpc,
IN char *inbuf,
OUT char *outbuf);
static __inline netaddr4* nfs41_rpc_netaddr(
IN nfs41_rpc_clnt *rpc)
{
uint32_t id;
AcquireSRWLockShared(&rpc->lock);
/* only addr_index needs to be protected, as rpc->addrs is write-once */
id = rpc->addr_index;
ReleaseSRWLockShared(&rpc->lock);
/* return the netaddr used to create the rpc client */
return &rpc->addrs.arr[id];
}
bool_t nfs41_renew_in_progress(nfs41_client *client, bool_t *value);
#endif /* __NFS41__ */

254
daemon/nfs41_callback.h Normal file
View file

@ -0,0 +1,254 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_CALLBACK_H__
#define __NFS41_CALLBACK_H__
//#include "nfs41.h"
#include "wintirpc.h"
#include "rpc/rpc.h"
#include "nfs41_types.h"
enum nfs41_callback_proc {
CB_NULL = 0,
CB_COMPOUND = 1,
};
enum nfs41_callback_op {
OP_CB_GETATTR = 3,
OP_CB_RECALL = 4,
OP_CB_LAYOUTRECALL = 5,
OP_CB_NOTIFY = 6,
OP_CB_PUSH_DELEG = 7,
OP_CB_RECALL_ANY = 8,
OP_CB_RECALLABLE_OBJ_AVAIL = 9,
OP_CB_RECALL_SLOT = 10,
OP_CB_SEQUENCE = 11,
OP_CB_WANTS_CANCELLED = 12,
OP_CB_NOTIFY_LOCK = 13,
OP_CB_NOTIFY_DEVICEID = 14,
OP_CB_ILLEGAL = 10044
};
int nfs41_handle_callback(void *, void *, void *);
/* OP_CB_LAYOUTRECALL */
struct cb_recall_file {
nfs41_fh fh;
uint64_t offset;
uint64_t length;
stateid4 stateid;
};
union cb_recall_file_args {
struct cb_recall_file file;
nfs41_fsid fsid;
};
struct cb_recall {
enum pnfs_return_type type;
union cb_recall_file_args args;
};
struct cb_layoutrecall_args {
enum pnfs_layout_type type;
enum pnfs_iomode iomode;
bool_t changed;
struct cb_recall recall;
};
struct cb_layoutrecall_res {
enum_t status;
};
/* OP_CB_RECALL_SLOT */
struct cb_recall_slot_args {
uint32_t target_highest_slotid;
};
struct cb_recall_slot_res {
enum_t status;
};
/* OP_CB_SEQUENCE */
struct cb_sequence_ref {
uint32_t sequenceid;
uint32_t slotid;
};
struct cb_sequence_ref_list {
char sessionid[NFS4_SESSIONID_SIZE];
struct cb_sequence_ref *calls;
uint32_t call_count;
};
struct cb_sequence_args {
char sessionid[NFS4_SESSIONID_SIZE];
uint32_t sequenceid;
uint32_t slotid;
uint32_t highest_slotid;
bool_t cachethis;
struct cb_sequence_ref_list *ref_lists;
uint32_t ref_list_count;
};
struct cb_sequence_res_ok {
char sessionid[NFS4_SESSIONID_SIZE];
uint32_t sequenceid;
uint32_t slotid;
uint32_t highest_slotid;
uint32_t target_highest_slotid;
};
struct cb_sequence_res {
enum_t status;
struct cb_sequence_res_ok ok;
};
/* OP_CB_GETATTR */
struct cb_getattr_args {
uint32_t target_highest_slotid;
};
struct cb_getattr_res {
enum_t status;
};
/* OP_CB_RECALL */
struct cb_recall_args {
stateid4 stateid;
bool_t truncate;
nfs41_fh fh;
};
struct cb_recall_res {
enum_t status;
};
/* OP_CB_NOTIFY */
struct cb_notify_args {
uint32_t target_highest_slotid;
};
struct cb_notify_res {
enum_t status;
};
/* OP_CB_PUSH_DELEG */
struct cb_push_deleg_args {
uint32_t target_highest_slotid;
};
struct cb_push_deleg_res {
enum_t status;
};
/* OP_CB_RECALL_ANY */
struct cb_recall_any_args {
uint32_t target_highest_slotid;
};
struct cb_recall_any_res {
enum_t status;
};
/* OP_CB_RECALLABLE_OBJ_AVAIL */
struct cb_recallable_obj_avail_args {
uint32_t target_highest_slotid;
};
struct cb_recallable_obj_avail_res {
enum_t status;
};
/* OP_CB_WANTS_CANCELLED */
struct cb_wants_cancelled_args {
uint32_t target_highest_slotid;
};
struct cb_wants_cancelled_res {
enum_t status;
};
/* OP_CB_NOTIFY_LOCK */
struct cb_notify_lock_args {
uint32_t target_highest_slotid;
};
struct cb_notify_lock_res {
enum_t status;
};
/* OP_CB_NOTIFY_DEVICEID */
struct cb_notify_deviceid_args {
uint32_t target_highest_slotid;
};
struct cb_notify_deviceid_res {
enum_t status;
};
/* CB_COMPOUND */
#define CB_COMPOUND_MAX_TAG 64
#define CB_COMPOUND_MAX_OPERATIONS 16
union cb_op_args {
struct cb_layoutrecall_args layoutrecall;
struct cb_recall_slot_args recall_slot;
struct cb_sequence_args sequence;
struct cb_recall_args recall;
};
struct cb_argop {
enum_t opnum;
union cb_op_args args;
};
struct cb_compound_tag {
char str[CB_COMPOUND_MAX_TAG];
uint32_t len;
};
struct cb_compound_args {
struct cb_compound_tag tag;
uint32_t minorversion;
uint32_t callback_ident; /* client MUST ignore */
struct cb_argop *argarray;
uint32_t argarray_count; /* <= CB_COMPOUND_MAX_OPERATIONS */
};
union cb_op_res {
struct cb_layoutrecall_res layoutrecall;
struct cb_recall_slot_res recall_slot;
struct cb_sequence_res sequence;
struct cb_recall_res recall;
};
struct cb_resop {
enum_t opnum;
union cb_op_res res;
};
struct cb_compound_res {
enum_t status;
struct cb_compound_tag tag;
struct cb_resop *resarray;
uint32_t resarray_count; /* <= CB_COMPOUND_MAX_OPERATIONS */
};
/* callback_xdr.c */
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args);
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res);
#endif /* !__NFS41_CALLBACK_H__ */

437
daemon/nfs41_client.c Normal file
View file

@ -0,0 +1,437 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include <time.h>
#include <winsock2.h>
#include <iphlpapi.h> /* for GetAdaptersAddresses() */
#include "rbtree.h"
#include "daemon_debug.h"
#include "nfs41_ops.h"
uint32_t nfs41_exchange_id_flags(
IN bool_t is_data)
{
uint32_t flags = EXCHGID4_FLAG_SUPP_MOVED_REFER;
if (is_data)
flags |= EXCHGID4_FLAG_USE_PNFS_DS;
else
flags |= EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS;
return flags;
}
static int pnfs_client_init(
IN nfs41_client *client)
{
enum pnfs_status pnfsstat;
int status = NO_ERROR;
/* initialize the pnfs layout and device lists for metadata clients */
pnfsstat = pnfs_file_layout_list_create(&client->layouts);
if (pnfsstat) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
pnfsstat = pnfs_file_device_list_create(&client->devices);
if (pnfsstat) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto out_err_layouts;
}
out:
return status;
out_err_layouts:
pnfs_file_layout_list_free(client->layouts);
client->layouts = NULL;
goto out;
}
static void update_server(
IN nfs41_client *client,
IN const char *server_scope,
IN const server_owner4 *owner)
{
nfs41_server *server;
int status;
/* find a server matching the owner.major_id and scope */
status = nfs41_server_find_or_create(owner->so_major_id,
server_scope, nfs41_rpc_netaddr(client->rpc), &server);
if (status == NO_ERROR) {
/* if the server is the same, we now have an extra reference. if
* the servers are different, we still need to deref the old server.
* so both cases can be treated the same */
if (client->server)
nfs41_server_deref(client->server);
client->server = server;
}
}
static void update_exchangeid_res(
IN nfs41_client *client,
IN const nfs41_exchange_id_res *exchangeid)
{
update_server(client, exchangeid->server_scope, &exchangeid->server_owner);
client->clnt_id = exchangeid->clientid;
client->seq_id = exchangeid->sequenceid;
client->roles = exchangeid->flags & EXCHGID4_FLAG_MASK_PNFS;
}
int nfs41_client_create(
IN nfs41_rpc_clnt *rpc,
IN const client_owner4 *owner,
IN bool_t is_data,
IN const nfs41_exchange_id_res *exchangeid,
OUT nfs41_client **client_out)
{
int status;
nfs41_client *client;
client = calloc(1, sizeof(nfs41_client));
if (client == NULL) {
status = GetLastError();
goto out_err_rpc;
}
client->cond = CreateEvent(NULL, TRUE, FALSE, "client_recovery_cond");
if (client->cond == NULL) {
status = GetLastError();
eprintf("CreateEvent failed %d\n", status);
goto out_err_rpc;
}
memcpy(&client->owner, owner, sizeof(client_owner4));
client->rpc = rpc;
client->is_data = is_data;
update_exchangeid_res(client, exchangeid);
//initialize a lock used to protect access to client id and client id seq#
InitializeSRWLock(&client->exid_lock);
status = pnfs_client_init(client);
if (status) {
eprintf("pnfs_client_init() failed with %d\n", status);
goto out_err_client;
}
*client_out = client;
out:
return status;
out_err_client:
nfs41_client_free(client); /* also calls nfs41_rpc_clnt_free() */
goto out;
out_err_rpc:
nfs41_rpc_clnt_free(rpc);
goto out;
}
static void dprint_roles(
IN int level,
IN uint32_t roles)
{
dprintf(level, "roles: %s%s%s\n",
(roles & EXCHGID4_FLAG_USE_NON_PNFS) ? "USE_NON_PNFS " : "",
(roles & EXCHGID4_FLAG_USE_PNFS_MDS) ? "USE_PNFS_MDS " : "",
(roles & EXCHGID4_FLAG_USE_PNFS_DS) ? "USE_PNFS_DS" : "");
}
int nfs41_client_renew(
IN nfs41_client *client)
{
nfs41_exchange_id_res exchangeid;
int status;
ZeroMemory(&exchangeid, sizeof(exchangeid));
status = nfs41_exchange_id(client->rpc, &client->owner,
nfs41_exchange_id_flags(client->is_data), &exchangeid);
if (status) {
eprintf("nfs41_exchange_id() failed with %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out;
}
if (client->is_data) { /* require USE_PNFS_DS */
if ((exchangeid.flags & EXCHGID4_FLAG_USE_PNFS_DS) == 0) {
eprintf("client expected USE_PNFS_DS\n");
status = ERROR_BAD_NET_RESP;
goto out;
}
} else { /* require USE_NON_PNFS or USE_PNFS_MDS */
if ((exchangeid.flags & EXCHGID4_FLAG_USE_NON_PNFS) == 0 &&
(exchangeid.flags & EXCHGID4_FLAG_USE_PNFS_MDS) == 0) {
eprintf("client expected USE_NON_PNFS OR USE_PNFS_MDS\n");
status = ERROR_BAD_NET_RESP;
goto out;
}
}
dprint_roles(2, exchangeid.flags);
AcquireSRWLockExclusive(&client->exid_lock);
update_exchangeid_res(client, &exchangeid);
ReleaseSRWLockExclusive(&client->exid_lock);
out:
return status;
}
bool_t nfs41_renew_in_progress(nfs41_client *client, bool_t *value)
{
bool_t status = FALSE;
if (value) {
dprintf(1, "nfs41_renew_in_progress: setting value %d\n", *value);
AcquireSRWLockExclusive(&client->exid_lock);
client->in_recovery = *value;
if (!client->in_recovery)
SetEvent(client->cond);
ReleaseSRWLockExclusive(&client->exid_lock);
} else {
AcquireSRWLockShared(&client->exid_lock);
status = client->in_recovery;
ReleaseSRWLockShared(&client->exid_lock);
dprintf(1, "nfs41_renew_in_progress: returning value %d\n", status);
}
return status;
}
void nfs41_client_free(
IN nfs41_client *client)
{
dprintf(2, "nfs41_client_free(%llu)\n", client->clnt_id);
if (client->session) nfs41_session_free(client->session);
if (client->server) nfs41_server_deref(client->server);
nfs41_rpc_clnt_free(client->rpc);
if (client->layouts) pnfs_file_layout_list_free(client->layouts);
if (client->devices) pnfs_file_device_list_free(client->devices);
CloseHandle(client->cond);
free(client);
}
/* client_owner generation
* we choose to use MAC addresses to generate a client_owner value that
* is unique to a machine and persists over restarts. because the client
* can have multiple network adapters/addresses, we take each adapter into
* account. the specification suggests that "for privacy reasons, it is
* best to perform some one-way function," so we apply an md5 hash to the
* sorted list of MAC addresses */
/* References:
* RFC 5661: 2.4. Client Identifiers and Client Owners
* http://tools.ietf.org/html/rfc5661#section-2.4
*
* MSDN: GetAdaptersAddresses Function
* http://msdn.microsoft.com/en-us/library/aa365915%28VS.85%29.aspx
*
* MSDN: Example C Program: Creating an MD5 Hash from File Content
* http://msdn.microsoft.com/en-us/library/aa382380%28VS.85%29.aspx */
/* use an rbtree to sort mac address entries */
struct mac_entry {
struct rb_node rbnode;
PBYTE address;
ULONG length;
};
static void mac_entry_insert(
IN struct rb_root *root,
IN PBYTE address,
IN ULONG length)
{
struct rb_node **node, *prev;
struct mac_entry *entry;
int diff;
node = &root->rb_node;
prev = NULL;
while (*node) {
entry = rb_entry(*node, struct mac_entry, rbnode);
prev = *node;
diff = length - entry->length;
if (diff == 0)
diff = memcmp(address, entry->address, length);
if (diff < 0)
node = &(*node)->rb_left;
else if (diff > 0)
node = &(*node)->rb_right;
else
return;
}
entry = calloc(1, sizeof(struct mac_entry));
if (entry) {
entry->address = address;
entry->length = length;
rb_link_node(&entry->rbnode, prev, node);
rb_insert_color(&entry->rbnode, root);
}
}
static int adapter_valid(
IN const IP_ADAPTER_ADDRESSES *addr)
{
/* ignore generic interfaces whose address is not unique */
switch (addr->IfType) {
case IF_TYPE_SOFTWARE_LOOPBACK:
case IF_TYPE_TUNNEL:
return 0;
}
/* must have an address */
if (addr->PhysicalAddressLength == 0)
return 0;
/* must support ip */
return addr->Ipv4Enabled || addr->Ipv6Enabled;
}
static DWORD hash_mac_addrs(
IN HCRYPTHASH hash)
{
PIP_ADAPTER_ADDRESSES addr, addrs = NULL;
struct rb_root rbtree = { NULL };
struct rb_node *node;
struct mac_entry *entry;
ULONG len;
DWORD status;
/* start with enough room for DEFAULT_MINIMUM_ENTITIES */
len = DEFAULT_MINIMUM_ENTITIES * sizeof(IP_ADAPTER_ADDRESSES);
do {
PIP_ADAPTER_ADDRESSES tmp;
/* reallocate the buffer until we can fit all of it */
tmp = realloc(addrs, len);
if (tmp == NULL) {
status = GetLastError();
goto out;
}
addrs = tmp;
status = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME |
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_UNICAST,
NULL, addrs, &len);
} while (status == ERROR_BUFFER_OVERFLOW);
if (status) {
eprintf("GetAdaptersAddresses() failed with %d\n", status);
goto out;
}
/* get the mac address of each adapter */
for (addr = addrs; addr; addr = addr->Next)
if (adapter_valid(addr))
mac_entry_insert(&rbtree, addr->PhysicalAddress,
addr->PhysicalAddressLength);
/* require at least one valid address */
node = rb_first(&rbtree);
if (node == NULL) {
status = ERROR_FILE_NOT_FOUND;
eprintf("GetAdaptersAddresses() did not return "
"any valid mac addresses, failing with %d.\n", status);
goto out;
}
while (node) {
entry = rb_entry(node, struct mac_entry, rbnode);
node = rb_next(node);
rb_erase(&entry->rbnode, &rbtree);
if (!CryptHashData(hash, entry->address, entry->length, 0)) {
status = GetLastError();
eprintf("CryptHashData() failed with %d\n", status);
/* don't break here, we need to free the rest */
}
free(entry);
}
out:
free(addrs);
return status;
}
int nfs41_client_owner(
OUT client_owner4 *owner)
{
HCRYPTPROV context;
HCRYPTHASH hash;
PBYTE buffer;
DWORD length;
const time_t time_created = time(NULL);
int status;
/* owner.verifier = "time created" */
ZeroMemory(owner->co_verifier, sizeof(owner->co_verifier));
memcpy(owner->co_verifier, &time_created, sizeof(time_created));
/* set up the md5 hash generator */
if (!CryptAcquireContext(&context, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
status = GetLastError();
eprintf("CryptAcquireContext() failed with %d\n", status);
goto out;
}
if (!CryptCreateHash(context, CALG_MD5, 0, 0, &hash)) {
status = GetLastError();
eprintf("CryptCreateHash() failed with %d\n", status);
goto out_context;
}
/* add the mac address from each applicable adapter to the hash */
status = hash_mac_addrs(hash);
if (status) {
eprintf("hash_mac_addrs() failed with %d\n", status);
goto out_hash;
}
/* extract the hash size (should always be 16 for md5) */
buffer = (PBYTE)&owner->co_ownerid_len;
length = (DWORD)sizeof(DWORD);
if (!CryptGetHashParam(hash, HP_HASHSIZE, buffer, &length, 0)) {
status = GetLastError();
eprintf("CryptGetHashParam(size) failed with %d\n", status);
goto out_hash;
}
/* extract the hash buffer */
buffer = owner->co_ownerid;
length = owner->co_ownerid_len;
if (!CryptGetHashParam(hash, HP_HASHVAL, buffer, &length, 0)) {
status = GetLastError();
eprintf("CryptGetHashParam(val) failed with %d\n", status);
goto out_hash;
}
out_hash:
CryptDestroyHash(hash);
out_context:
CryptReleaseContext(context, 0);
out:
return status;
}

333
daemon/nfs41_compound.c Normal file
View file

@ -0,0 +1,333 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <stdio.h>
#include <stdlib.h>
#include "nfs41_compound.h"
#include "nfs41_xdr.h"
#include "nfs41_ops.h"
#include "name_cache.h"
#include "daemon_debug.h"
#define BUF_SIZE 1024
int compound_error(int status)
{
if (status != NFS4_OK)
dprintf(1, "COMPOUND failed with status %d.\n", status);
return status;
}
static void compound_args_init(
nfs41_compound_args *compound,
nfs_argop4 *argarray)
{
compound->tag_len = 8;
memcpy(compound->tag, "ms-nfs41", 8);
compound->minorversion = 1;
compound->argarray_count = 0;
compound->argarray = argarray;
}
static void compound_args_add_op(
nfs41_compound_args *compound,
uint32_t opnum,
void *arg)
{
const uint32_t i = compound->argarray_count++;
compound->argarray[i].op = opnum;
compound->argarray[i].arg = arg;
}
static void compound_res_init(
nfs41_compound_res *compound,
nfs_resop4 *resarray)
{
ZeroMemory(compound, sizeof(nfs41_compound_res));
compound->tag_len = NFS4_OPAQUE_LIMIT;
compound->resarray_count = 0;
compound->resarray = resarray;
}
static void compound_res_add_op(
nfs41_compound_res *compound,
void *res)
{
compound->resarray[compound->resarray_count++].res = res;
}
void compound_init(
nfs41_compound *compound,
nfs_argop4 *argops,
nfs_resop4 *resops)
{
compound_args_init(&compound->args, argops);
compound_res_init(&compound->res, resops);
}
void compound_add_op(
nfs41_compound *compound,
uint32_t opnum,
void *arg,
void *res)
{
compound_args_add_op(&compound->args, opnum, arg);
compound_res_add_op(&compound->res, res);
}
/* Due to the possibility of replays, we might get a response to a different
* call than the one we're expecting. If we don't have a way to check for
* this, we'll likely crash trying to decode into the wrong structures.
* This function copies the number of operations and all of the operation
* numbers from the compound arguments into the response, so we can verify
* them on decode and fail before doing any damage. */
static void set_expected_res(
nfs41_compound *compound)
{
uint32_t i;
compound->res.resarray_count = compound->args.argarray_count;
for (i = 0; i < compound->res.resarray_count; i++)
compound->res.resarray[i].op = compound->args.argarray[i].op;
}
int check_renew_in_progress(
IN nfs41_session *session)
{
int status = 0;
bool_t one = 1, zero = 0;;
while (nfs41_renew_in_progress(session->client, NULL)) {
status = WaitForSingleObject(session->client->cond, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_renew_in_progress: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
nfs41_renew_in_progress(session->client, &zero);
status = 1;
}
nfs41_renew_in_progress(session->client, &one);
out:
return status;
}
int compound_encode_send_decode(
nfs41_session *session,
nfs41_compound *compound,
uint32_t bufsize_in,
uint32_t bufsize_out)
{
int status, retry_count = 0, delayby = 0;
nfs41_sequence_args *args =
(nfs41_sequence_args *)compound->args.argarray[0].arg;
bool_t zero = 0;
retry:
/* send compound */
retry_count++;
set_expected_res(compound);
status = nfs41_send_compound(session->client->rpc,
(char *)&compound->args, (char *)&compound->res);
if (status) {
eprintf("nfs41_send_compound failed %d for seqid=%d, slotid=%d\n",
status, args->sa_sequenceid, args->sa_slotid);
status = NFS4ERR_IO;
goto out_free_slot;
} else {
// bump sequence number if sequence op succeeded
if (compound->res.resarray_count > 0 &&
compound->res.resarray[0].op == OP_SEQUENCE) {
nfs41_sequence_res *seq =
(nfs41_sequence_res *)compound->res.resarray[0].res;
if (seq->sr_status == NFS4_OK) {
// returned slotid must be the same we sent
status = NFS4ERR_IO;
if (seq->sr_resok4.sr_slotid != args->sa_slotid) {
eprintf("[session] sr_slotid=%d != sa_slotid=%d\n",
seq->sr_resok4.sr_slotid, args->sa_slotid);
goto out_free_slot;
}
// returned sessionid must be the same we sent
if (memcmp(seq->sr_resok4.sr_sessionid, args->sa_sessionid,
NFS4_SESSIONID_SIZE)) {
eprintf("[session] sr_sessionid != sa_sessionid\n");
print_hexbuf(1, (unsigned char *)"sr_sessionid",
seq->sr_resok4.sr_sessionid, NFS4_SESSIONID_SIZE);
print_hexbuf(1, (unsigned char *)"sa_sessionid",
args->sa_sessionid, NFS4_SESSIONID_SIZE);
goto out_free_slot;
}
if (seq->sr_resok4.sr_status_flags)
print_sr_status_flags(1, seq->sr_resok4.sr_status_flags);
status = nfs41_session_bump_seq(session, args->sa_slotid);
if (status)
goto out_free_slot;
}
}
}
if (compound->res.status != NFS4_OK)
dprintf(1, "\n################ %s ################\n\n",
nfs_error_string(compound->res.status));
if (compound->res.status != NFS4_OK &&
compound->args.argarray[0].op == OP_DESTROY_SESSION) {
dprintf(1, "OP_DESTROY_SESSION ignoring errors\n");
compound->res.status = NFS4_OK;
}
switch (compound->res.status) {
case NFS4_OK:
break;
case NFS4ERR_STALE_CLIENTID:
//try to create a new client
status = check_renew_in_progress(session);
if (status == ERROR_LOCK_VIOLATION)
goto out_free_slot;
else if (status == 1)
goto do_retry;
status = nfs41_client_renew(session->client);
if (status) {
eprintf("nfs41_exchange_id() failed with %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out;
}
//fallthru and reestablish the session
case NFS4ERR_BADSESSION:
//try to create a new session
if (compound->res.status == NFS4ERR_BADSESSION) {
status = check_renew_in_progress(session);
if (status == ERROR_LOCK_VIOLATION)
goto out_free_slot;
else if (status == 1)
goto do_retry;
}
status = nfs41_session_renew(session);
if (status == NFS4ERR_STALE_CLIENTID) {
status = nfs41_client_renew(session->client);
if (status) {
eprintf("nfs41_exchange_id() failed with %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out;
}
status = nfs41_session_renew(session);
if (status) {
eprintf("after reestablishing clientid: nfs41_session_renew() "
"failed with %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out;
}
} else if (status && status != NFS4ERR_STALE_CLIENTID) {
eprintf("nfs41_session_renew: failed with %d\n", status);
goto out;
}
if (nfs41_renew_in_progress(session->client, NULL))
nfs41_renew_in_progress(session->client, &zero);
goto do_retry;
case NFS4ERR_GRACE:
case NFS4ERR_DELAY:
#define RETRY_INDEFINITELY
#ifndef RETRY_INDEFINITELY
#define NUMBER_2_RETRY 19
#endif
#ifndef RETRY_INDEFINITELY
if (retry_count < NUMBER_2_RETRY) {
#endif
if (compound->args.argarray[0].op == OP_SEQUENCE) {
nfs41_sequence_args *seq = (nfs41_sequence_args*)
compound->args.argarray[0].arg;
nfs41_session_free_slot(session, seq->sa_slotid);
}
if (compound->res.status == NFS4ERR_GRACE)
delayby = 5000;
else
delayby = 500*retry_count;
dprintf(1, "Compound returned %s: sleeping for %ums..\n",
(compound->res.status==NFS4ERR_GRACE)?"NFS4ERR_GRACE":"NFS4ERR_DELAY",
delayby);
Sleep(delayby);
dprintf(1, "Attempting to resend compound.\n");
goto do_retry;
#ifndef RETRY_INDEFINITELY
}
#endif
break;
case NFS4ERR_FHEXPIRED: /* TODO: recover expired volatile filehandles */
status = NFS4ERR_STALE; /* for now, treat them as ERR_STALE */
/* no break */
case NFS4ERR_STALE:
{
nfs_argop4 *argarray = compound->args.argarray;
struct nfs41_name_cache *name_cache =
session_name_cache(session);
nfs41_putfh_args *putfh;
uint32_t i, start = 0;
/* NFS4ERR_STALE generally comes from a PUTFH operation. in
* this case, remove its filehandle from the name cache. but
* because COMPOUNDs are not atomic, a file can be removed
* between PUTFH and the operation that uses it. in this
* case, we can't tell which PUTFH operation is to blame, so
* we must invalidate filehandles of all PUTFH operations in
* the COMPOUND */
if (argarray[compound->res.resarray_count-1].op == OP_PUTFH)
start = compound->res.resarray_count-1;
for (i = start; i < compound->res.resarray_count; i++) {
if (argarray[i].op == OP_PUTFH) {
putfh = (nfs41_putfh_args*)argarray[i].arg;
if (!putfh->in_recovery)
nfs41_name_cache_remove_stale(name_cache,
session, putfh->file->path);
}
}
}
break;
}
out_free_slot:
if (compound->args.argarray[0].op == OP_SEQUENCE) {
nfs41_sequence_args *seq = (nfs41_sequence_args *)compound->args.argarray[0].arg;
nfs41_session_free_slot(session, seq->sa_slotid);
}
out:
return status;
do_retry:
if (compound->res.resarray[0].op == OP_SEQUENCE) {
nfs41_sequence_args *seq = (nfs41_sequence_args*)
compound->args.argarray[0].arg;
status = nfs41_session_get_slot(session, &seq->sa_slotid,
&seq->sa_sequenceid, &seq->sa_highest_slotid);
if (status)
goto out;
}
goto retry;
}

82
daemon/nfs41_compound.h Normal file
View file

@ -0,0 +1,82 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_DAEMON_COMPOUND_H__
#define __NFS41_DAEMON_COMPOUND_H__
#include "nfs41.h"
/* COMPOUND */
typedef struct __nfs_argop4 {
uint32_t op;
void *arg;
} nfs_argop4;
typedef struct __nfs41_compound_args {
uint32_t tag_len;
unsigned char tag[NFS4_OPAQUE_LIMIT];
uint32_t minorversion;
uint32_t argarray_count;
nfs_argop4 *argarray; /* <> */
} nfs41_compound_args;
typedef struct __nfs_resop4 {
uint32_t op;
void *res;
} nfs_resop4;
typedef struct __nfs41_compound_res {
uint32_t status;
uint32_t tag_len;
unsigned char tag[NFS4_OPAQUE_LIMIT];
uint32_t resarray_count;
nfs_resop4 *resarray; /* <> */
} nfs41_compound_res;
typedef struct __nfs41_compound {
nfs41_compound_args args;
nfs41_compound_res res;
} nfs41_compound;
int compound_error(int status);
void compound_init(
nfs41_compound *compound,
nfs_argop4 *argops,
nfs_resop4 *resops);
void compound_add_op(
nfs41_compound *compound,
uint32_t opnum,
void *arg,
void *res);
int compound_encode_send_decode(
nfs41_session *session,
nfs41_compound *compound,
uint32_t bufsize_in,
uint32_t bufsize_out);
#endif /* __NFS41_DAEMON_COMPOUND_H__ */

306
daemon/nfs41_const.h Normal file
View file

@ -0,0 +1,306 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_NFS_CONST_H__
#define __NFS41_NFS_CONST_H__
/*
* Sizes
*/
#define NFS4_FHSIZE 128
#define NFS4_VERIFIER_SIZE 8
#define NFS4_OPAQUE_LIMIT 1024
#define NFS4_SESSIONID_SIZE 16
#define NFS41_MAX_FILEIO_SIZE (1024 * 1024)
#define NFS41_MAX_SERVER_CACHE 1024
#define NFS41_MAX_RPC_REQS 128
#define NFS41_MAX_COMPONENT_SIZE 64
#define UPCALL_BUF_SIZE 1024
/* see MaximumComponentNameLength in FileFsAttributeInformation
* in nfs41_driver.c:nfs41_QueryVolumeInformation() */
#define NFS41_MAX_COMPONENT_LEN 64
#define NFS41_MAX_PATH_LEN MAX_PATH
#define NFS41_HOSTNAME_LEN 64
#define NFS41_ADDRS_PER_SERVER 4
/* max length of ipv6 address 48
* sizeof(".255.255") + 8 */
#define NFS41_UNIVERSAL_ADDR_LEN 56
/* "udp" "tcp" "udp6" "tcp6" */
#define NFS41_NETWORK_ID_LEN 4
/* 424 bytes: max rpc header for reply with data */
/* 32 bytes: max COMPOUND response */
/* 40 bytes: max SEQUENCE response */
/* 4 bytes: max PUTFH response */
/* 12 bytes: max READ response */
#define READ_OVERHEAD 512
/* 840 bytes: max rpc header for call */
/* 32 bytes: max COMPOUND request */
/* 32 bytes: max SEQUENCE request */
/* 132 bytes: max PUTFH request */
/* 32 bytes: max WRITE request */
#define WRITE_OVERHEAD 1068
#define NFS41_RPC_PROGRAM 100003
#define NFS41_RPC_VERSION 4
#define NFS41_RPC_CBPROGRAM 0x2358
/*
* Error status
*/
enum nfsstat4 {
NFS4_OK = 0, /* everything is okay */
NFS4ERR_PERM = 1, /* caller not privileged */
NFS4ERR_NOENT = 2, /* no such file/directory */
NFS4ERR_IO = 5, /* hard I/O error */
NFS4ERR_NXIO = 6, /* no such device */
NFS4ERR_ACCESS = 13, /* access denied */
NFS4ERR_EXIST = 17, /* file already exists */
NFS4ERR_XDEV = 18, /* different filesystems */
NFS4ERR_NOTDIR = 20, /* should be a directory */
NFS4ERR_ISDIR = 21, /* should not be directory */
NFS4ERR_INVAL = 22, /* invalid argument */
NFS4ERR_FBIG = 27, /* file exceeds server max */
NFS4ERR_NOSPC = 28, /* no space on filesystem */
NFS4ERR_ROFS = 30, /* read-only filesystem */
NFS4ERR_MLINK = 31, /* too many hard links */
NFS4ERR_NAMETOOLONG = 63, /* name exceeds server max */
NFS4ERR_NOTEMPTY = 66, /* directory not empty */
NFS4ERR_DQUOT = 69, /* hard quota limit reached*/
NFS4ERR_STALE = 70, /* file no longer exists */
NFS4ERR_BADHANDLE = 10001, /* Illegal filehandle */
NFS4ERR_BAD_COOKIE = 10003, /* READDIR cookie is stale */
NFS4ERR_NOTSUPP = 10004, /* operation not supported */
NFS4ERR_TOOSMALL = 10005, /* response limit exceeded */
NFS4ERR_SERVERFAULT = 10006, /* undefined server error */
NFS4ERR_BADTYPE = 10007, /* type invalid for CREATE */
NFS4ERR_DELAY = 10008, /* file "busy" - retry */
NFS4ERR_SAME = 10009, /* nverify says attrs same */
NFS4ERR_DENIED = 10010, /* lock unavailable */
NFS4ERR_EXPIRED = 10011, /* lock lease expired */
NFS4ERR_LOCKED = 10012, /* I/O failed due to lock */
NFS4ERR_GRACE = 10013, /* in grace period */
NFS4ERR_FHEXPIRED = 10014, /* filehandle expired */
NFS4ERR_SHARE_DENIED = 10015, /* share reserve denied */
NFS4ERR_WRONGSEC = 10016, /* wrong security flavor */
NFS4ERR_CLID_INUSE = 10017, /* clientid in use */
/* NFS4ERR_RESOURCE is not a valid error in NFSv4.1 */
NFS4ERR_RESOURCE = 10018, /* resource exhaustion */
NFS4ERR_MOVED = 10019, /* filesystem relocated */
NFS4ERR_NOFILEHANDLE = 10020, /* current FH is not set */
NFS4ERR_MINOR_VERS_MISMATCH = 10021, /* minor vers not supp */
NFS4ERR_STALE_CLIENTID = 10022, /* server has rebooted */
NFS4ERR_STALE_STATEID = 10023, /* server has rebooted */
NFS4ERR_OLD_STATEID = 10024, /* state is out of sync */
NFS4ERR_BAD_STATEID = 10025, /* incorrect stateid */
NFS4ERR_BAD_SEQID = 10026, /* request is out of seq. */
NFS4ERR_NOT_SAME = 10027, /* verify - attrs not same */
NFS4ERR_LOCK_RANGE = 10028, /* overlapping lock range */
NFS4ERR_SYMLINK = 10029, /* should be file/directory*/
NFS4ERR_RESTOREFH = 10030, /* no saved filehandle */
NFS4ERR_LEASE_MOVED = 10031, /* some filesystem moved */
NFS4ERR_ATTRNOTSUPP = 10032, /* recommended attr not sup*/
NFS4ERR_NO_GRACE = 10033, /* reclaim outside of grace*/
NFS4ERR_RECLAIM_BAD = 10034, /* reclaim error at server */
NFS4ERR_RECLAIM_CONFLICT = 10035, /* conflict on reclaim */
NFS4ERR_BADXDR = 10036, /* XDR decode failed */
NFS4ERR_LOCKS_HELD = 10037, /* file locks held at CLOSE*/
NFS4ERR_OPENMODE = 10038, /* conflict in OPEN and I/O*/
NFS4ERR_BADOWNER = 10039, /* owner translation bad */
NFS4ERR_BADCHAR = 10040, /* utf-8 char not supported*/
NFS4ERR_BADNAME = 10041, /* name not supported */
NFS4ERR_BAD_RANGE = 10042, /* lock range not supported*/
NFS4ERR_LOCK_NOTSUPP = 10043, /* no atomic up/downgrade */
NFS4ERR_OP_ILLEGAL = 10044, /* undefined operation */
NFS4ERR_DEADLOCK = 10045, /* file locking deadlock */
NFS4ERR_FILE_OPEN = 10046, /* open file blocks op. */
NFS4ERR_ADMIN_REVOKED = 10047, /* lockowner state revoked */
NFS4ERR_CB_PATH_DOWN = 10048, /* callback path down */
/* NFSv4.1 errors start here. */
NFS4ERR_BADIOMODE = 10049,
NFS4ERR_BADLAYOUT = 10050,
NFS4ERR_BAD_SESSION_DIGEST = 10051,
NFS4ERR_BADSESSION = 10052,
NFS4ERR_BADSLOT = 10053,
NFS4ERR_COMPLETE_ALREADY = 10054,
NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
NFS4ERR_DELEG_ALREADY_WANTED = 10056,
NFS4ERR_BACK_CHAN_BUSY = 10057, /*backchan reqs outstanding*/
NFS4ERR_LAYOUTTRYLATER = 10058,
NFS4ERR_LAYOUTUNAVAILABLE = 10059,
NFS4ERR_NOMATCHING_LAYOUT = 10060,
NFS4ERR_RECALLCONFLICT = 10061,
NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
NFS4ERR_SEQ_MISORDERED = 10063, /* unexpected seq.ID in req*/
NFS4ERR_SEQUENCE_POS = 10064, /* [CB_]SEQ. op not 1st op */
NFS4ERR_REQ_TOO_BIG = 10065, /* request too big */
NFS4ERR_REP_TOO_BIG = 10066, /* reply too big */
NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067, /* rep. not all cached */
NFS4ERR_RETRY_UNCACHED_REP = 10068, /* retry & rep. uncached */
NFS4ERR_UNSAFE_COMPOUND = 10069, /* retry/recovery too hard */
NFS4ERR_TOO_MANY_OPS = 10070, /*too many ops in [CB_]COMP*/
NFS4ERR_OP_NOT_IN_SESSION = 10071, /* op needs [CB_]SEQ. op */
NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp. */
/* Error 10073 is unused. */
NFS4ERR_CLIENTID_BUSY = 10074, /* clientid has state */
NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */
NFS4ERR_SEQ_FALSE_RETRY = 10076, /* Retry != original req. */
NFS4ERR_BAD_HIGH_SLOT = 10077, /* req has bad highest_slot*/
NFS4ERR_DEADSESSION = 10078, /*new req sent to dead sess*/
NFS4ERR_ENCR_ALG_UNSUPP = 10079, /* encr alg. not supp. */
NFS4ERR_PNFS_NO_LAYOUT = 10080, /* I/O without a layout */
NFS4ERR_NOT_ONLY_OP = 10081, /* addl ops not allowed */
NFS4ERR_WRONG_CRED = 10082, /* op done by wrong cred */
NFS4ERR_WRONG_TYPE = 10083, /* op on wrong type object */
NFS4ERR_DIRDELEG_UNAVAIL = 10084, /* delegation not avail. */
NFS4ERR_REJECT_DELEG = 10085, /* cb rejected delegation */
NFS4ERR_RETURNCONFLICT = 10086, /* layout get before return*/
NFS4ERR_DELEG_REVOKED = 10087 /* deleg./layout revoked */
};
#define MAKE_WORD0(XXX) (1 << XXX)
#define MAKE_WORD1(XXX) (1 << (XXX-32))
#define MAKE_WORD2(XXX) (1 << (XXX-64))
enum {
/*
* Mandatory Attributes
*/
FATTR4_WORD0_SUPPORTED_ATTRS = MAKE_WORD0(0),
FATTR4_WORD0_TYPE = MAKE_WORD0(1),
FATTR4_WORD0_FH_EXPIRE_TYPE = MAKE_WORD0(2),
FATTR4_WORD0_CHANGE = MAKE_WORD0(3),
FATTR4_WORD0_SIZE = MAKE_WORD0(4),
FATTR4_WORD0_LINK_SUPPORT = MAKE_WORD0(5),
FATTR4_WORD0_SYMLINK_SUPPORT = MAKE_WORD0(6),
FATTR4_WORD0_NAMED_ATTR = MAKE_WORD0(7),
FATTR4_WORD0_FSID = MAKE_WORD0(8),
FATTR4_WORD0_UNIQUE_HANDLES = MAKE_WORD0(9),
FATTR4_WORD0_LEASE_TIME = MAKE_WORD0(10),
FATTR4_WORD0_RDATTR_ERROR = MAKE_WORD0(11),
FATTR4_WORD0_FILEHANDLE = MAKE_WORD0(19),
FATTR4_WORD2_SUPPATTR_EXCLCREAT = MAKE_WORD2(75),
/*
* Recommended Attributes
*/
FATTR4_WORD0_ACL = MAKE_WORD0(12),
FATTR4_WORD0_ACLSUPPORT = MAKE_WORD0(13),
FATTR4_WORD0_ARCHIVE = MAKE_WORD0(14),
FATTR4_WORD0_CANSETTIME = MAKE_WORD0(15),
FATTR4_WORD0_CASE_INSENSITIVE = MAKE_WORD0(16),
FATTR4_WORD0_CASE_PRESERVING = MAKE_WORD0(17),
FATTR4_WORD0_CHOWN_RESTRICTED = MAKE_WORD0(18),
FATTR4_WORD0_FILEID = MAKE_WORD0(20),
FATTR4_WORD0_FILES_AVAIL = MAKE_WORD0(21),
FATTR4_WORD0_FILES_FREE = MAKE_WORD0(22),
FATTR4_WORD0_FILES_TOTAL = MAKE_WORD0(23),
FATTR4_WORD0_FS_LOCATIONS = MAKE_WORD0(24),
FATTR4_WORD0_HIDDEN = MAKE_WORD0(25),
FATTR4_WORD0_HOMOGENEOUS = MAKE_WORD0(26),
FATTR4_WORD0_MAXFILESIZE = MAKE_WORD0(27),
FATTR4_WORD0_MAXLINK = MAKE_WORD0(28),
FATTR4_WORD0_MAXNAME = MAKE_WORD0(29),
FATTR4_WORD0_MAXREAD = MAKE_WORD0(30),
FATTR4_WORD0_MAXWRITE = MAKE_WORD0(31),
FATTR4_WORD1_MIMETYPE = MAKE_WORD1(32),
FATTR4_WORD1_MODE = MAKE_WORD1(33),
FATTR4_WORD1_NO_TRUNC = MAKE_WORD1(34),
FATTR4_WORD1_NUMLINKS = MAKE_WORD1(35),
FATTR4_WORD1_OWNER = MAKE_WORD1(36),
FATTR4_WORD1_OWNER_GROUP = MAKE_WORD1(37),
FATTR4_WORD1_QUOTA_AVAIL_HARD = MAKE_WORD1(38),
FATTR4_WORD1_QUOTA_AVAIL_SOFT = MAKE_WORD1(39),
FATTR4_WORD1_QUOTA_USED = MAKE_WORD1(40),
FATTR4_WORD1_RAWDEV = MAKE_WORD1(41),
FATTR4_WORD1_SPACE_AVAIL = MAKE_WORD1(42),
FATTR4_WORD1_SPACE_FREE = MAKE_WORD1(43),
FATTR4_WORD1_SPACE_TOTAL = MAKE_WORD1(44),
FATTR4_WORD1_SPACE_USED = MAKE_WORD1(45),
FATTR4_WORD1_SYSTEM = MAKE_WORD1(46),
FATTR4_WORD1_TIME_ACCESS = MAKE_WORD1(47),
FATTR4_WORD1_TIME_ACCESS_SET = MAKE_WORD1(48),
FATTR4_WORD1_TIME_BACKUP = MAKE_WORD1(49),
FATTR4_WORD1_TIME_CREATE = MAKE_WORD1(50),
FATTR4_WORD1_TIME_DELTA = MAKE_WORD1(51),
FATTR4_WORD1_TIME_METADATA = MAKE_WORD1(52),
FATTR4_WORD1_TIME_MODIFY = MAKE_WORD1(53),
FATTR4_WORD1_TIME_MODIFY_SET = MAKE_WORD1(54),
FATTR4_WORD1_MOUNTED_ON_FILEID = MAKE_WORD1(55),
FATTR4_WORD1_DIR_NOTIF_DELAY = MAKE_WORD1(56),
FATTR4_WORD1_DIRENT_NOTIF_DELAY = MAKE_WORD1(57),
FATTR4_WORD1_DACL = MAKE_WORD1(58),
FATTR4_WORD1_SACL = MAKE_WORD1(59),
FATTR4_WORD1_CHANGE_POLICY = MAKE_WORD1(60),
FATTR4_WORD1_FS_STATUS = MAKE_WORD1(61),
FATTR4_WORD1_FS_LAYOUT_TYPE = MAKE_WORD1(62),
FATTR4_WORD1_LAYOUT_HINT = MAKE_WORD1(63),
FATTR4_WORD2_LAYOUT_TYPE = MAKE_WORD2(64),
FATTR4_WORD2_LAYOUT_BLKSIZE = MAKE_WORD2(65),
FATTR4_WORD2_LAYOUT_ALIGNMENT = MAKE_WORD2(66),
FATTR4_WORD2_FS_LOCATIONS_INFO = MAKE_WORD2(67),
FATTR4_WORD2_MDSTHRESHOLD = MAKE_WORD2(68),
FATTR4_WORD2_RETENTION_GET = MAKE_WORD2(69),
FATTR4_WORD2_RETENTION_SET = MAKE_WORD2(70),
FATTR4_WORD2_RETENTEVT_GET = MAKE_WORD2(71),
FATTR4_WORD2_RETENTEVT_SET = MAKE_WORD2(72),
FATTR4_WORD2_RETENTION_HOLD = MAKE_WORD2(73),
FATTR4_WORD2_MODE_SET_MASKED = MAKE_WORD2(74),
FATTR4_WORD2_FS_CHARSET_CAP = MAKE_WORD2(76),
};
/*
* File types
*/
enum nfs_ftype4 {
NF4REG = 1, /* Regular File */
NF4DIR = 2, /* Directory */
NF4BLK = 3, /* Special File - block device */
NF4CHR = 4, /* Special File - character device */
NF4LNK = 5, /* Symbolic Link */
NF4SOCK = 6, /* Special File - socket */
NF4FIFO = 7, /* Special File - fifo */
NF4ATTRDIR = 8, /* Attribute Directory */
NF4NAMEDATTR = 9, /* Named Attribute */
NFS_FTYPE_MASK = 0xF
};
#define CREATE_SESSION4_FLAG_CONN_BACK_CHAN 0x00000002;
#endif /* !__NFS41_NFS_CONST_H__ */

217
daemon/nfs41_daemon.c Normal file
View file

@ -0,0 +1,217 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <devioctl.h>
#include "nfs41_driver.h" /* for NFS41_USER_DEVICE_NAME_A */
#include "nfs41_np.h" /* for NFS41NP_SHARED_MEMORY */
#include "daemon_debug.h"
#include "upcall.h"
#include "util.h"
#define MAX_NUM_THREADS 128
BOOLEAN CREATED_SESSION = FALSE;
typedef struct _nfs41_process_thread {
HANDLE handle;
uint32_t tid;
} nfs41_process_thread;
DWORD InitSharedMemory(
OUT PHANDLE phMutex)
{
DWORD status = NO_ERROR;
*phMutex = CreateMutex(NULL, FALSE, TEXT(NFS41NP_MUTEX_NAME));
if (*phMutex == NULL) {
status = GetLastError();
eprintf("CreateMutex failed with %d\n", status);
}
return status;
}
static unsigned int WINAPI thread_main(void *args)
{
DWORD status = 0;
HANDLE pipe;
// buffer used to process upcall, assumed to be fixed size.
// if we ever need to handle non-cached IO, need to make it dynamic
unsigned char outbuf[UPCALL_BUF_SIZE];
// buffer used to send downcall content, need to dynamically allocated
// as we don't know the length of the buffer (ie. size of directory listing
unsigned char *inbuf = NULL;
DWORD inbuf_len, outbuf_len;
nfs41_upcall upcall;
pipe = CreateFile(NFS41_USER_DEVICE_NAME_A, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
eprintf("Unable to open upcall pipe %d\n", GetLastError());
return GetLastError();
}
while(1) {
status = DeviceIoControl(pipe, IOCTL_NFS41_READ, NULL, 0,
outbuf, UPCALL_BUF_SIZE, (LPDWORD)&outbuf_len, NULL);
if (!status) {
eprintf("IOCTL_NFS41_READ failed %d\n", GetLastError());
continue;
}
status = upcall_parse(outbuf, (uint32_t)outbuf_len, &upcall);
if (status)
goto write_downcall;
#if 1 //AGLO: this is just a placeholder for a real solution. I know this variable needs a lock in a
//normal case. However, this does not prevent us from receiving an upcall for an old mount
//that was not reestablished. It will only work for erroring requests until the 1st mount upcall.
if (!CREATED_SESSION && (upcall.opcode != NFS41_MOUNT && upcall.opcode != NFS41_SHUTDOWN)) {
eprintf("nfs41_daemon restarted and does not have a valid session established\n");
upcall.status = 116;
goto write_downcall;
}
#endif
if (upcall.opcode == NFS41_SHUTDOWN) {
printf("Shutting down..\n");
exit(0);
}
status = upcall_handle(&upcall);
#if 1 //AGLO: place holder for a real solution
if (upcall.opcode == NFS41_MOUNT && upcall.status == NO_ERROR)
CREATED_SESSION = 1;
#endif
write_downcall:
dprintf(1, "writing downcall: xid=%d opcode=%s status=%d "
"get_last_error=%d\n", upcall.xid, opcode2string(upcall.opcode),
upcall.status, upcall.last_error);
if (upcall.opcode == NFS41_DIR_QUERY)
inbuf_len = UPCALL_BUF_SIZE + upcall.args.readdir.query_reply_len;
else
inbuf_len = UPCALL_BUF_SIZE;
inbuf = malloc(inbuf_len);
status = upcall_marshall(&upcall, inbuf, (uint32_t)inbuf_len, (uint32_t*)&outbuf_len);
dprintf(2, "making a downcall: outbuf_len %ld\n", outbuf_len);
status = DeviceIoControl(pipe, IOCTL_NFS41_WRITE,
inbuf, inbuf_len, NULL, 0, (LPDWORD)&outbuf_len, NULL);
free(inbuf);
if (!status) {
eprintf("IOCTL_NFS41_WRITE failed with %d xid=%d opcode=%s\n",
GetLastError(), upcall.xid, opcode2string(upcall.opcode));
status = upcall_cancel(&upcall);
continue;
}
dprintf(3, "downcall returned %d\n", status);
printf("\n");
}
CloseHandle(pipe);
return GetLastError();
}
void __cdecl _tmain(int argc, TCHAR *argv[])
{
DWORD status = 0, len;
// handles related to shared memory
HANDLE hSharedMemoryMutex;
// handle to our drivers
HANDLE pipe;
nfs41_process_thread tids[MAX_NUM_THREADS];
int i;
if (argc > 2) {
const char *process = strip_path(argv[0], NULL);
printf("Usage: %s [#debug level]\n", process);
} else if (argc == 2) {
set_debug_level(_ttoi(argv[1]));
}
#ifdef _DEBUG
/* dump memory leaks to stderr on exit; this requires the debug heap,
/* available only when built in debug mode under visual studio -cbodley */
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
dprintf(1, "debug mode. dumping memory leaks to stderr on exit.\n");
#endif
nfs41_server_list_init();
pipe = CreateFile(NFS41_USER_DEVICE_NAME_A, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
eprintf("Unable to open upcall pipe %d\n", GetLastError());
return;
}
status = InitSharedMemory(&hSharedMemoryMutex);
if (status)
goto quit_pipe;
dprintf(1, "starting nfs41 mini redirector\n");
status = DeviceIoControl(pipe, IOCTL_NFS41_START,
NULL, 0, NULL, 0, (LPDWORD)&len, NULL);
if (!status) {
eprintf("IOCTL_NFS41_START failed with %d\n",
GetLastError());
goto quit;
}
for (i = 0; i < MAX_NUM_THREADS; i++) {
tids[i].handle = (HANDLE)_beginthreadex(NULL, 0, thread_main,
NULL, 0, &tids[i].tid);
if (tids[i].handle == INVALID_HANDLE_VALUE) {
status = GetLastError();
eprintf("_beginthreadex failed %d\n", status);
goto quit_pipe;
}
}
//This can be changed to waiting on an array of handles and using waitformultipleobjects
dprintf(1, "Parent waiting for children threads\n");
for (i = 0; i < MAX_NUM_THREADS; i++)
WaitForSingleObject(tids[i].handle, INFINITE );
dprintf(1, "Parent woke up!!!!\n");
quit:
CloseHandle(hSharedMemoryMutex);
quit_pipe:
CloseHandle(pipe);
return;
}

1745
daemon/nfs41_ops.c Normal file

File diff suppressed because it is too large Load diff

1074
daemon/nfs41_ops.h Normal file

File diff suppressed because it is too large Load diff

298
daemon/nfs41_rpc.c Normal file
View file

@ -0,0 +1,298 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include "nfs41.h"
#include "daemon_debug.h"
#include "nfs41_xdr.h"
#include "nfs41_callback.h"
#include "rpc/rpc.h"
static enum clnt_stat send_null(CLIENT *client)
{
struct timeval timeout = {10, 0};
return clnt_call(client, 0,
(xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_void, NULL, timeout);
}
static int get_client_for_netaddr(
IN const netaddr4 *netaddr,
IN uint32_t wsize,
IN uint32_t rsize,
IN nfs41_rpc_clnt *rpc,
OUT CLIENT **client_out)
{
int status = ERROR_NETWORK_UNREACHABLE;
struct netconfig *nconf;
struct netbuf *addr;
CLIENT *client;
nconf = getnetconfigent(netaddr->netid);
if (nconf == NULL)
goto out;
addr = uaddr2taddr(nconf, netaddr->uaddr);
if (addr == NULL)
goto out_free_conf;
dprintf(1, "callback function %p args %p\n", nfs41_handle_callback, rpc);
client = clnt_tli_create(RPC_ANYFD, nconf, addr,
NFS41_RPC_PROGRAM, NFS41_RPC_VERSION, wsize, rsize,
rpc?proc_cb_compound_res:NULL, rpc?nfs41_handle_callback:NULL, rpc?rpc:NULL);
if (client) {
*client_out = client;
status = NO_ERROR;
goto out_free_addr;
}
out_free_addr:
freenetbuf(addr);
out_free_conf:
freenetconfigent(nconf);
out:
return status;
}
static int get_client_for_multi_addr(
IN const multi_addr4 *addrs,
IN uint32_t wsize,
IN uint32_t rsize,
IN nfs41_rpc_clnt *rpc,
OUT CLIENT **client_out,
OUT uint32_t *addr_index)
{
int status = ERROR_NETWORK_UNREACHABLE;
uint32_t i;
for (i = 0; i < addrs->count; i++) {
status = get_client_for_netaddr(&addrs->arr[i],
wsize, rsize, rpc, client_out);
if (status == NO_ERROR) {
*addr_index = i;
break;
}
}
return status;
}
/* Returns a client structure and an associated lock */
int nfs41_rpc_clnt_create(
IN const multi_addr4 *addrs,
IN uint32_t wsize,
IN uint32_t rsize,
bool_t needcb,
OUT nfs41_rpc_clnt **rpc_out)
{
CLIENT *client;
nfs41_rpc_clnt *rpc;
uint32_t addr_index;
int status;
rpc = calloc(1, sizeof(nfs41_rpc_clnt));
if (rpc == NULL) {
status = GetLastError();
goto out;
}
rpc->cond = CreateEvent(NULL, TRUE, FALSE, "rpc_recovery_cond");
if (rpc->cond == NULL) {
status = GetLastError();
fprintf(stderr, "CreateEvent failed %d\n", status);
goto out_free_rpc_clnt;
}
status = get_client_for_multi_addr(addrs,
wsize, rsize, needcb?rpc:NULL, &client, &addr_index);
if (status) {
clnt_pcreateerror("connecting failed");
goto out_free_rpc_clnt;
}
// XXX Pick credentials in better manner
client->cl_auth = authsys_create_default();
if (client->cl_auth == NULL) {
// XXX log failure in auth creation somewhere
// XXX Better error return
status = ERROR_NETWORK_UNREACHABLE;
goto out_err_client;
}
if (send_null(client) != RPC_SUCCESS) {
// XXX Do what here?
dprintf(1, " send_null failed\n");
status = ERROR_NETWORK_UNREACHABLE;
goto out_err_auth;
}
rpc->rpc = client;
/* keep a copy of the address and buffer sizes for reconnect */
memcpy(&rpc->addrs, addrs, sizeof(multi_addr4));
/* save the index of the address we connected to */
rpc->addr_index = addr_index;
rpc->wsize = wsize;
rpc->rsize = rsize;
rpc->is_valid_session = TRUE;
//initialize rpc client lock
InitializeSRWLock(&rpc->lock);
*rpc_out = rpc;
out:
return status;
out_err_auth:
auth_destroy(client->cl_auth);
out_err_client:
CloseHandle(rpc->cond);
clnt_destroy(client);
out_free_rpc_clnt:
free(rpc);
goto out;
}
/* Frees resources allocated in clnt_create */
void nfs41_rpc_clnt_free(
IN nfs41_rpc_clnt *rpc)
{
auth_destroy(rpc->rpc->cl_auth);
clnt_destroy(rpc->rpc);
CloseHandle(rpc->cond);
free(rpc);
}
static bool_t rpc_renew_in_progress(nfs41_rpc_clnt *rpc, int *value)
{
bool_t status = FALSE;
AcquireSRWLockExclusive(&rpc->lock);
if (value) {
dprintf(1, "nfs41_rpc_renew_in_progress: setting value %d\n", *value);
rpc->in_recovery = *value;
if (!rpc->in_recovery)
SetEvent(rpc->cond);
} else {
status = rpc->in_recovery;
dprintf(1, "nfs41_rpc_renew_in_progress: returning value %d\n", status);
}
ReleaseSRWLockExclusive(&rpc->lock);
return status;
}
static bool_t rpc_should_retry(nfs41_rpc_clnt *rpc, uint32_t version)
{
bool_t status = 0;
AcquireSRWLockExclusive(&rpc->lock);
if (rpc->version > version)
status = 1;
ReleaseSRWLockExclusive(&rpc->lock);
return status;
}
static int rpc_reconnect(
IN nfs41_rpc_clnt *rpc)
{
CLIENT *client = NULL;
uint32_t addr_index;
int status;
AcquireSRWLockExclusive(&rpc->lock);
status = get_client_for_multi_addr(&rpc->addrs,
rpc->wsize, rpc->rsize, rpc, &client, &addr_index);
if (status)
goto out_unlock;
client->cl_auth = rpc->rpc->cl_auth;
if (send_null(client) != RPC_SUCCESS)
goto out_err_client;
clnt_destroy(rpc->rpc);
rpc->rpc = client;
rpc->addr_index = addr_index;
rpc->version++;
dprintf(1, "nfs41_send_compound: reestablished RPC connection\n");
out_unlock:
ReleaseSRWLockExclusive(&rpc->lock);
return status;
out_err_client:
clnt_destroy(client);
goto out_unlock;
}
int nfs41_send_compound(
IN nfs41_rpc_clnt *rpc,
IN char *inbuf,
OUT char *outbuf)
{
struct timeval timeout = {10, 0};
enum clnt_stat rpc_status;
int status, count = 0, one = 1, zero = 0;
uint32_t version;
try_again:
AcquireSRWLockShared(&rpc->lock);
version = rpc->version;
rpc_status = clnt_call(rpc->rpc, 1,
(xdrproc_t)nfs_encode_compound, inbuf,
(xdrproc_t)nfs_decode_compound, outbuf,
timeout);
ReleaseSRWLockShared(&rpc->lock);
if (rpc_status != RPC_SUCCESS) {
eprintf("clnt_call returned rpc_status=%i\n", rpc_status);
switch(rpc_status) {
case RPC_CANTRECV:
case RPC_CANTSEND:
case RPC_TIMEDOUT:
if (!rpc->is_valid_session && ++count > 3) {
status = ERROR_NETWORK_UNREACHABLE;
break;
}
if (rpc_should_retry(rpc, version))
goto try_again;
while (rpc_renew_in_progress(rpc, NULL)) {
status = WaitForSingleObject(rpc->cond, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_rpc_renew_in_progress: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
rpc_renew_in_progress(rpc, &zero);
goto try_again;
}
rpc_renew_in_progress(rpc, &one);
if (rpc_reconnect(rpc))
eprintf("Failed to reconnect!\n");
rpc_renew_in_progress(rpc, &zero);
goto try_again;
default:
eprintf("UNHANDLED RPC_ERROR: %d\n", rpc_status);
status = ERROR_NETWORK_UNREACHABLE;
break;
}
goto out;
}
status = 0;
out:
return status;
}

332
daemon/nfs41_server.c Normal file
View file

@ -0,0 +1,332 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include <stdio.h>
#include "wintirpc.h"
#include "rpc/rpc.h"
#include "name_cache.h"
#include "daemon_debug.h"
#include "nfs41.h"
#include "util.h"
#define SRVLVL 2 /* dprintf level for server logging */
/* nfs41_server_list */
struct server_list {
struct list_entry head;
CRITICAL_SECTION lock;
};
static struct server_list g_server_list;
#define server_entry(pos) list_container(pos, nfs41_server, entry)
void nfs41_server_list_init()
{
list_init(&g_server_list.head);
InitializeCriticalSection(&g_server_list.lock);
}
/* http://tools.ietf.org/html/rfc5661#section-1.6
* 1.6. General Definitions: Server Owner:
* "When the client has two connections each to a peer with the same major
* identifier, the client assumes that both peers are the same server (the
* server namespace is the same via each connection)" */
/* http://tools.ietf.org/html/rfc5661#section-2.10.4
* 2.10.4. Server Scope
* "When the server scope values are the same, server owner value may be
* validly compared. In cases where the server scope values are different,
* server owner values are treated as different even if they contain all
* identical bytes." */
/* given these definitions, we require that both the server_owner.major_id
* and server_scope are identical when matching instances of nfs41_server */
struct server_info {
const char *scope;
const char *owner;
};
static int server_compare(
const struct list_entry *entry,
const void *value)
{
const nfs41_server *server = server_entry(entry);
const struct server_info *info = (const struct server_info*)value;
const int diff = strncmp(server->scope, info->scope, NFS4_OPAQUE_LIMIT);
return diff ? diff : strncmp(server->owner, info->owner, NFS4_OPAQUE_LIMIT);
}
static int server_entry_find(
IN struct server_list *servers,
IN const struct server_info *info,
OUT struct list_entry **entry_out)
{
*entry_out = list_search(&servers->head, info, server_compare);
return *entry_out ? NO_ERROR : ERROR_FILE_NOT_FOUND;
}
static int server_create(
IN const struct server_info *info,
OUT nfs41_server **server_out)
{
int status = NO_ERROR;
nfs41_server *server;
server = calloc(1, sizeof(nfs41_server));
if (server == NULL) {
status = GetLastError();
eprintf("failed to allocate server %s\n", info->owner);
goto out;
}
StringCchCopyA(server->scope, NFS4_OPAQUE_LIMIT, info->scope);
StringCchCopyA(server->owner, NFS4_OPAQUE_LIMIT, info->owner);
InitializeSRWLock(&server->addrs.lock);
nfs41_superblock_list_init(&server->superblocks);
nfs41_name_cache_create(&server->name_cache);
*server_out = server;
out:
return status;
}
static void server_free(
IN nfs41_server *server)
{
dprintf(SRVLVL, "server_free(%s)\n", server->owner);
nfs41_superblock_list_free(&server->superblocks);
nfs41_name_cache_free(&server->name_cache);
free(server);
}
static __inline void server_ref_locked(
IN nfs41_server *server)
{
server->ref_count++;
dprintf(SRVLVL, "nfs41_server_ref(%s) count %d\n",
server->owner, server->ref_count);
}
void nfs41_server_ref(
IN nfs41_server *server)
{
EnterCriticalSection(&g_server_list.lock);
server_ref_locked(server);
LeaveCriticalSection(&g_server_list.lock);
}
void nfs41_server_deref(
IN nfs41_server *server)
{
EnterCriticalSection(&g_server_list.lock);
server->ref_count--;
dprintf(SRVLVL, "nfs41_server_deref(%s) count %d\n",
server->owner, server->ref_count);
if (server->ref_count == 0) {
list_remove(&server->entry);
server_free(server);
}
LeaveCriticalSection(&g_server_list.lock);
}
static void server_addrs_add(
IN OUT struct server_addrs *addrs,
IN const netaddr4 *addr)
{
/* we keep a list of addrs used to connect to each server. once it gets
* bigger than NFS41_ADDRS_PER_SERVER, overwrite the oldest addrs. use
* server_addrs.next_index to implement a circular array */
AcquireSRWLockExclusive(&addrs->lock);
if (multi_addr_find(&addrs->addrs, addr, NULL)) {
dprintf(SRVLVL, "server_addrs_add() found existing addr '%s'.\n",
addr->uaddr);
} else {
/* overwrite the address at 'next_index' */
StringCchCopyA(addrs->addrs.arr[addrs->next_index].netid,
NFS41_NETWORK_ID_LEN, addr->netid);
StringCchCopyA(addrs->addrs.arr[addrs->next_index].uaddr,
NFS41_UNIVERSAL_ADDR_LEN, addr->uaddr);
/* increment/wrap next_index */
addrs->next_index = (addrs->next_index + 1) % NFS41_ADDRS_PER_SERVER;
/* update addrs.count if necessary */
if (addrs->addrs.count < addrs->next_index)
addrs->addrs.count = addrs->next_index;
dprintf(SRVLVL, "server_addrs_add() added new addr '%s'.\n",
addr->uaddr);
}
ReleaseSRWLockExclusive(&addrs->lock);
}
void nfs41_server_addrs(
IN nfs41_server *server,
OUT multi_addr4 *addrs)
{
struct server_addrs *saddrs = &server->addrs;
uint32_t i, j;
/* make a copy of the server's addrs, with most recent first */
AcquireSRWLockShared(&saddrs->lock);
j = saddrs->next_index;
for (i = 0; i < saddrs->addrs.count; i++) {
/* decrement/wrap j */
j = (NFS41_ADDRS_PER_SERVER + j - 1) % NFS41_ADDRS_PER_SERVER;
memcpy(&addrs->arr[i], &saddrs->addrs.arr[j], sizeof(netaddr4));
}
ReleaseSRWLockShared(&saddrs->lock);
}
int nfs41_server_find_or_create(
IN const char *server_owner_major_id,
IN const char *server_scope,
IN const netaddr4 *addr,
OUT nfs41_server **server_out)
{
const struct server_info info = { server_scope, server_owner_major_id };
struct list_entry *entry;
nfs41_server *server;
int status;
dprintf(SRVLVL, "--> nfs41_server_find_or_create(%s)\n", info.owner);
EnterCriticalSection(&g_server_list.lock);
/* search for an existing server */
status = server_entry_find(&g_server_list, &info, &entry);
if (status) {
/* create a new server */
status = server_create(&info, &server);
if (status == NO_ERROR) {
/* add it to the list */
list_add_tail(&g_server_list.head, &server->entry);
*server_out = server;
dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
"returning new server %p\n", server);
} else {
dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
"returning %d\n", status);
}
} else {
server = server_entry(entry);
dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
"returning existing server %p\n", server);
}
if (server) {
/* register the address used to connect */
server_addrs_add(&server->addrs, addr);
server_ref_locked(server);
}
*server_out = server;
LeaveCriticalSection(&g_server_list.lock);
return status;
}
int nfs41_server_resolve(
IN const char *hostname,
IN unsigned short port,
OUT multi_addr4 *addrs)
{
int status = ERROR_BAD_NET_NAME;
char service[16];
struct addrinfo hints, *res, *info;
struct netconfig *nconf;
struct netbuf addr;
char *netid, *uaddr;
dprintf(SRVLVL, "--> nfs41_server_resolve(%s:%u)\n",
hostname, port);
addrs->count = 0;
StringCchPrintfA(service, 16, "%u", port);
/* request a list of tcp addrs for the given hostname,port */
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(hostname, service, &hints, &res) != 0)
goto out;
for (info = res; info != NULL; info = info->ai_next) {
/* find the appropriate entry in /etc/netconfig */
switch (info->ai_family) {
case AF_INET: netid = "tcp"; break;
case AF_INET6: netid = "tcp6"; break;
default: continue;
}
nconf = getnetconfigent(netid);
if (nconf == NULL)
continue;
/* convert to a transport-independent universal address */
addr.buf = info->ai_addr;
addr.maxlen = addr.len = (unsigned int)info->ai_addrlen;
uaddr = taddr2uaddr(nconf, &addr);
freenetconfigent(nconf);
if (uaddr == NULL)
continue;
StringCchCopyA(addrs->arr[addrs->count].netid,
NFS41_NETWORK_ID_LEN+1, netid);
StringCchCopyA(addrs->arr[addrs->count].uaddr,
NFS41_UNIVERSAL_ADDR_LEN+1, uaddr);
freeuaddr(uaddr);
status = NO_ERROR;
if (++addrs->count >= NFS41_ADDRS_PER_SERVER)
break;
}
freeaddrinfo(res);
out:
if (status)
dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
"error %d\n", hostname, port, status);
else
dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
"%s\n", hostname, port, addrs->arr[0].uaddr);
return status;
}

385
daemon/nfs41_session.c Normal file
View file

@ -0,0 +1,385 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <process.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "nfs41_ops.h"
#include "util.h"
/* session slot mechanism */
static int init_slot_table(nfs41_slot_table *table)
{
int i, status = 0;
//initialize slot table lock
table->lock = CreateMutex(NULL, FALSE, "session_table_lock");
if (table->lock == NULL) {
status = GetLastError();
eprintf("CreateMutext failed %d\n", status);
goto out;
}
//initialize condition variable for slots
table->cond = CreateEvent(NULL, TRUE, FALSE, "session_table_cond");
if (table->cond == NULL) {
status = GetLastError();
eprintf("CreateEvent failed %d\n", status);
goto out_mutex;
}
table->max_slots = NFS41_MAX_NUM_SLOTS;
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
table->seq_nums[i] = 1;
table->used_slots[i] = 0;
}
table->highest_used = 0;
out:
return status;
out_mutex:
CloseHandle(table->lock);
goto out;
}
static int reinit_slot_table(nfs41_slot_table *table)
{
int i, status = 0;
status = WaitForSingleObject(table->lock, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_session_bump_seq: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
table->max_slots = NFS41_MAX_NUM_SLOTS;
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
table->seq_nums[i] = 1;
table->used_slots[i] = 0;
}
table->highest_used = 0;
SetEvent(table->cond);
ReleaseMutex(table->lock);
out:
return status;
}
static void free_slot_table(nfs41_slot_table *table)
{
CloseHandle(table->lock);
CloseHandle(table->cond);
}
int nfs41_session_bump_seq(
IN nfs41_session *session,
IN uint32_t slotid)
{
int status;
AcquireSRWLockShared(&session->client->session_lock);
status = WaitForSingleObject(session->table.lock, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_session_bump_seq: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
session->table.seq_nums[slotid]++;
ReleaseMutex(session->table.lock);
out:
ReleaseSRWLockShared(&session->client->session_lock);
return status;
}
int nfs41_session_free_slot(
IN nfs41_session *session,
IN uint32_t slotid)
{
int status, i;
AcquireSRWLockShared(&session->client->session_lock);
status = WaitForSingleObject(session->table.lock, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_session_free_slot: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
session->table.used_slots[slotid] = 0;
if (slotid == session->table.highest_used) {
session->table.highest_used = 0;
for (i = slotid; i > 0; i--) {
if (session->table.used_slots[i]) {
session->table.highest_used = i;
break;
}
}
}
dprintf(3, "freeing slot#=%d highest=%d\n", slotid, session->table.highest_used);
SetEvent(session->table.cond);
ReleaseMutex(session->table.lock);
out:
ReleaseSRWLockShared(&session->client->session_lock);
return status;
}
int nfs41_session_get_slot(
IN nfs41_session *session,
OUT uint32_t *slot,
OUT uint32_t *seq,
OUT uint32_t *highest)
{
uint32_t status = NO_ERROR;
uint32_t i;
AcquireSRWLockShared(&session->client->session_lock);
look_for_slot:
status = WaitForSingleObject(session->table.lock, INFINITE);
if (status != WAIT_OBJECT_0) {
dprintf(1, "nfs41_session_get_slot: WaitForSingleObject failed\n");
print_condwait_status(1, status);
status = ERROR_LOCK_VIOLATION;
goto out;
}
dprintf(3, "looking for a free slot in the slot table\n");
*highest = session->table.highest_used;
for (i = 0; i < session->table.max_slots; i++) {
if (!session->table.used_slots[i]) {
session->table.used_slots[i] = 1; // mark slot used
*slot = i; // return slot number
*seq = session->table.seq_nums[i]; // return sequence number for the slot
//update highest_slot_used if needed
if (i > session->table.highest_used)
*highest = session->table.highest_used = i;
break;
}
}
if (i == session->table.max_slots) {
dprintf(1, "all (%d) slots are used. waiting for a free slot\n", session->table.max_slots);
ReleaseMutex(session->table.lock);
status = WaitForSingleObject(session->table.cond, INFINITE);
if (status == WAIT_OBJECT_0) {
dprintf(1, "received a signal to look for a free slot\n");
ResetEvent(session->table.cond);
goto look_for_slot;
}
}
ReleaseMutex(session->table.lock);
dprintf(2, "session %p: using slot#=%d with seq#=%d highest=%d\n", session, *slot, *seq, *highest);
out:
ReleaseSRWLockShared(&session->client->session_lock);
return status;
}
int nfs41_session_sequence(
nfs41_sequence_args *args,
nfs41_session *session,
bool_t cachethis)
{
uint32_t status = NO_ERROR;
status = nfs41_session_get_slot(session, &args->sa_slotid,
&args->sa_sequenceid, &args->sa_highest_slotid);
if (status)
goto out;
args->sa_sessionid = session->session_id;
args->sa_cachethis = cachethis;
out:
return status;
}
/* session renewal */
static unsigned int WINAPI renew_session(void *args)
{
int status = NO_ERROR;
nfs41_session *session = (nfs41_session *)args;
/* sleep for 2/3 of lease_time */
const uint32_t sleep_time = (2 * session->lease_time*1000)/3;
dprintf(1, "Creating renew_session thread: %p\n", session->renew_thread);
while(1) {
dprintf(1, "Going to sleep for %dmsecs\n", sleep_time);
Sleep(sleep_time);
status = nfs41_send_sequence(session);
if (status)
dprintf(1, "renewal thread: nfs41_send_sequence failed %d\n", status);
}
return status;
}
/* session creation */
static int session_alloc(
IN nfs41_client *client,
OUT nfs41_session **session_out)
{
int status;
nfs41_session *session;
session = calloc(1, sizeof(nfs41_session));
if (session == NULL) {
status = GetLastError();
goto out;
}
session->client = client;
session->renew_thread = INVALID_HANDLE_VALUE;
session->isValidState = FALSE;
status = init_slot_table(&session->table);
if (status) {
eprintf("init_slot_table failed %d\n", status);
goto out_err_session;
}
//initialize session lock
InitializeSRWLock(&client->session_lock);
*session_out = session;
out:
return status;
out_err_session:
free(session);
goto out;
}
int nfs41_session_create(
IN nfs41_client *client,
IN nfs41_session **session_out)
{
nfs41_session *session;
int status;
status = session_alloc(client, &session);
if (status) {
eprintf("session_alloc() failed with %d\n", status);
goto out;
}
AcquireSRWLockShared(&client->exid_lock);
if (client->roles & (EXCHGID4_FLAG_USE_PNFS_MDS |
EXCHGID4_FLAG_USE_NON_PNFS))
session->flags |= CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
ReleaseSRWLockShared(&client->exid_lock);
status = nfs41_create_session(client, session);
if (status) {
eprintf("nfs41_create_session failed %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out_err;
}
AcquireSRWLockExclusive(&session->client->session_lock);
client->session = session;
session->isValidState = TRUE;
ReleaseSRWLockExclusive(&session->client->session_lock);
*session_out = session;
out:
return status;
out_err:
nfs41_session_free(session);
goto out;
}
/* session renewal */
int nfs41_session_renew(
IN nfs41_session *session)
{
int status;
AcquireSRWLockExclusive(&session->client->session_lock);
status = reinit_slot_table(&session->table);
if (status) {
eprintf("init_slot_table failed %d\n", status);
goto out_err_session;
}
status = nfs41_create_session(session->client, session);
if (status && status != NFS4ERR_STALE_CLIENTID) {
eprintf("nfs41_create_session failed %d\n", status);
status = ERROR_BAD_NET_RESP;
goto out_err_slot;
}
ReleaseSRWLockExclusive(&session->client->session_lock);
out:
return status;
out_err_slot:
free_slot_table(&session->table);
out_err_session:
ReleaseSRWLockExclusive(&session->client->session_lock);
free(session);
goto out;
}
int nfs41_session_set_lease(
IN nfs41_session *session,
IN uint32_t lease_time)
{
int status = NO_ERROR;
uint32_t thread_id;
if (valid_handle(session->renew_thread)) {
eprintf("nfs41_session_set_lease(): session "
"renewal thread already started!\n");
goto out;
}
if (lease_time == 0) {
eprintf("nfs41_session_set_lease(): invalid lease_time=0\n");
status = ERROR_INVALID_PARAMETER;
goto out;
}
session->lease_time = lease_time;
session->renew_thread = (HANDLE)_beginthreadex(NULL,
0, renew_session, session, 0, &thread_id);
if (!valid_handle(session->renew_thread)) {
status = GetLastError();
eprintf("_beginthreadex failed %d\n", status);
goto out;
}
out:
return status;
}
void nfs41_session_free(
IN nfs41_session *session)
{
AcquireSRWLockExclusive(&session->client->session_lock);
if (valid_handle(session->renew_thread)) {
dprintf(1, "nfs41_session_free: terminating session renewal thread\n");
if (!TerminateThread(session->renew_thread, NO_ERROR))
eprintf("failed to terminate renewal thread %p\n",
session->renew_thread);
}
if (session->isValidState) {
session->client->rpc->is_valid_session = FALSE;
nfs41_destroy_session(session);
}
free_slot_table(&session->table);
ReleaseSRWLockExclusive(&session->client->session_lock);
free(session);
}

228
daemon/nfs41_superblock.c Normal file
View file

@ -0,0 +1,228 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "nfs41.h"
#include "nfs41_ops.h"
#include "util.h"
#define SBLVL 3 /* dprintf level for superblock logging */
static __inline int compare_fsid(
IN const nfs41_fsid *lhs,
IN const nfs41_fsid *rhs)
{
if (lhs->major > rhs->major) return 1;
if (lhs->major < rhs->major) return -1;
if (lhs->minor > rhs->minor) return 1;
if (lhs->minor < rhs->minor) return -1;
return 0;
}
/* nfs41_superblock */
static int superblock_create(
IN const nfs41_fsid *fsid,
OUT nfs41_superblock **superblock_out)
{
int status = NO_ERROR;
nfs41_superblock *superblock;
dprintf(SBLVL, "creating superblock for fsid(%llu,%llu)\n",
fsid->major, fsid->minor);
superblock = calloc(1, sizeof(nfs41_superblock));
if (superblock == NULL) {
status = GetLastError();
eprintf("failed to allocate superblock "
"for fsid(%llu,%llu)\n", fsid->major, fsid->minor);
goto out;
}
memcpy(&superblock->fsid, fsid, sizeof(nfs41_fsid));
InitializeSRWLock(&superblock->lock);
*superblock_out = superblock;
out:
return status;
}
static void superblock_free(
IN nfs41_superblock *superblock)
{
free(superblock);
}
static int get_superblock_attrs(
IN nfs41_session *session,
IN nfs41_superblock *superblock,
IN nfs41_path_fh *file)
{
int status;
bitmap4 attr_request;
nfs41_file_info info;
attr_request.arr[0] = (uint32_t)(FATTR4_WORD0_SUPPORTED_ATTRS |
FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE);
attr_request.arr[1] = FATTR4_WORD1_FS_LAYOUT_TYPE;
attr_request.count = 2;
ZeroMemory(&info, sizeof(info));
info.supported_attrs = &superblock->supported_attrs;
status = nfs41_getattr(session, file, &attr_request, &info);
if (status) {
eprintf("nfs41_getattr() failed with %s when "
"fetching attributes for fsid(%llu,%llu)\n",
nfs_error_string(status),
superblock->fsid.major, superblock->fsid.minor);
goto out;
}
if (info.maxread)
superblock->maxread = info.maxread;
else
superblock->maxread = session->fore_chan_attrs.ca_maxresponsesize;
if (info.maxwrite)
superblock->maxwrite = info.maxwrite;
else
superblock->maxwrite = session->fore_chan_attrs.ca_maxrequestsize;
superblock->layout_types = info.fs_layout_types;
dprintf(SBLVL, "attributes for fsid(%llu,%llu): "
"maxread=%llu, maxwrite=%llu, layout_types: 0x%X\n",
superblock->fsid.major, superblock->fsid.minor,
superblock->maxread, superblock->maxwrite,
superblock->layout_types);
out:
return status;
}
/* nfs41_superblock_list */
#define superblock_entry(pos) list_container(pos, nfs41_superblock, entry)
static int superblock_compare(
const struct list_entry *entry,
const void *value)
{
const nfs41_superblock *superblock = superblock_entry(entry);
return compare_fsid(&superblock->fsid, (const nfs41_fsid*)value);
}
static nfs41_superblock* find_superblock(
IN nfs41_superblock_list *superblocks,
IN const nfs41_fsid *fsid)
{
struct list_entry *entry;
entry = list_search(&superblocks->head, fsid, superblock_compare);
return entry ? superblock_entry(entry) : NULL;
}
void nfs41_superblock_list_init(
IN nfs41_superblock_list *superblocks)
{
list_init(&superblocks->head);
InitializeSRWLock(&superblocks->lock);
}
void nfs41_superblock_list_free(
IN nfs41_superblock_list *superblocks)
{
struct list_entry *entry, *tmp;
dprintf(SBLVL, "nfs41_superblock_list_free()\n");
list_for_each_tmp(entry, tmp, &superblocks->head)
superblock_free(superblock_entry(entry));
}
int nfs41_superblock_for_fh(
IN nfs41_session *session,
IN const nfs41_fsid *fsid,
IN const nfs41_fh *parent OPTIONAL,
OUT nfs41_path_fh *file)
{
int status = NFS4_OK;
nfs41_server *server = client_server(session->client);
nfs41_superblock_list *superblocks = &server->superblocks;
nfs41_superblock *superblock;
dprintf(SBLVL, "--> nfs41_superblock_for_fh(fsid(%llu,%llu))\n",
fsid->major, fsid->minor);
/* compare with the parent's fsid, and use that if it matches */
if (parent && parent->superblock &&
compare_fsid(fsid, &parent->superblock->fsid) == 0) {
file->fh.superblock = parent->superblock;
dprintf(SBLVL, "using superblock from parent\n");
goto out;
}
/* using a shared lock, search for an existing superblock */
AcquireSRWLockShared(&superblocks->lock);
superblock = find_superblock(superblocks, fsid);
ReleaseSRWLockShared(&superblocks->lock);
if (superblock) {
dprintf(SBLVL, "found existing superblock in server list "
"[shared lock]\n");
} else {
AcquireSRWLockExclusive(&superblocks->lock);
/* must search again under an exclusive lock, in case another thread
* created it after our first search */
superblock = find_superblock(superblocks, fsid);
if (superblock) {
dprintf(SBLVL, "found newly created superblock in server list "
"[exclusive lock]\n");
} else {
/* create the superblock */
status = superblock_create(fsid, &superblock);
if (status == NO_ERROR) /* add it to the list */
list_add_tail(&superblocks->head, &superblock->entry);
}
ReleaseSRWLockExclusive(&superblocks->lock);
}
if (status == NO_ERROR && superblock->supported_attrs.count == 0) {
/* exclusive lock on the superblock while fetching attributes */
AcquireSRWLockExclusive(&superblock->lock);
if (superblock->supported_attrs.count == 0)
status = get_superblock_attrs(session, superblock, file);
ReleaseSRWLockExclusive(&superblock->lock);
}
file->fh.superblock = superblock;
out:
dprintf(SBLVL, "<-- nfs41_superblock_for_fh() returning %p, status %d\n",
file->fh.superblock, status);
return status;
}

185
daemon/nfs41_types.h Normal file
View file

@ -0,0 +1,185 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_DAEMON_TYPES_H__
#define __NFS41_DAEMON_TYPES_H__
#include "wintirpc.h"
#include "rpc/xdr.h"
#include "nfs41_const.h"
typedef char* caddr_t;
static const int64_t NFS4_INT64_MAX = 0x7fffffffffffffff;
static const uint64_t NFS4_UINT64_MAX = 0xffffffffffffffff;
static const int32_t NFS4_INT32_MAX = 0x7fffffff;
static const uint32_t NFS4_UINT32_MAX = 0xffffffff;
static const uint64_t NFS4_MAXFILELEN = 0xffffffffffffffff;
static const uint64_t NFS4_MAXFILEOFF = 0xfffffffffffffffe;
/* common nfs types */
typedef struct __nfs41_abs_path {
char path[NFS41_MAX_PATH_LEN];
unsigned short len;
SRWLOCK lock;
} nfs41_abs_path;
typedef struct __nfs41_component {
const char *name;
unsigned short len;
} nfs41_component;
typedef struct __nfs41_fh {
unsigned char fh[NFS4_FHSIZE];
uint32_t len;
uint64_t fileid;
struct __nfs41_superblock *superblock;
} nfs41_fh;
typedef struct __nfs41_path_fh {
nfs41_abs_path *path;
nfs41_component name;
nfs41_fh fh;
} nfs41_path_fh;
typedef struct __nfs41_fsid {
uint64_t major;
uint64_t minor;
} nfs41_fsid;
typedef struct __netaddr4 {
char netid[NFS41_NETWORK_ID_LEN+1];
char uaddr[NFS41_UNIVERSAL_ADDR_LEN+1];
} netaddr4;
typedef struct __multi_addr4 {
netaddr4 arr[NFS41_ADDRS_PER_SERVER];
uint32_t count;
} multi_addr4;
typedef struct __bitmap4 {
uint32_t count;
uint32_t arr[3];
} bitmap4;
typedef struct __nfstime4 {
int64_t seconds;
uint32_t nseconds;
} nfstime4;
typedef struct __client_owner4 {
unsigned char co_verifier[NFS4_VERIFIER_SIZE];
uint32_t co_ownerid_len;
unsigned char co_ownerid[NFS4_OPAQUE_LIMIT];
} client_owner4;
typedef struct __server_owner4 {
uint64_t so_minor_id;
uint32_t so_major_id_len;
char so_major_id[NFS4_OPAQUE_LIMIT];
} server_owner4;
typedef struct __state_owner4 {
uint32_t owner_len;
unsigned char owner[NFS4_OPAQUE_LIMIT];
} state_owner4;
typedef struct __nfs_impl_id4 {
uint32_t nii_domain_len;
unsigned char *nii_domain;
uint32_t nii_name_len;
unsigned char *nii_name;
nfstime4 nii_date;
} nfs_impl_id4;
typedef struct __nfsace4 {
uint32_t acetype;
uint32_t aceflag;
uint32_t acemask;
unsigned char who[NFS4_OPAQUE_LIMIT];
} nfsace4;
typedef struct __stateid4 {
uint32_t seqid;
unsigned char other[12];
} stateid4;
typedef struct __fattr4 {
bitmap4 attrmask;
uint32_t attr_vals_len;
unsigned char attr_vals[NFS4_OPAQUE_LIMIT];
} fattr4;
typedef struct __change_info4 {
bool_t atomic;
uint64_t before;
uint64_t after;
} change_info4;
typedef struct __fs_location_server {
/* 'address' represents one of a traditional DNS host name,
* IPv4 address, IPv6 address, or a zero-length string */
char address[NFS41_HOSTNAME_LEN+1];
} fs_location_server;
typedef struct __fs_location4 {
nfs41_abs_path path; /* path to fs from referred server's root */
fs_location_server *servers;
uint32_t server_count;
} fs_location4;
typedef struct __fs_locations4 {
nfs41_abs_path path; /* path to fs from referring server's root */
fs_location4 *locations;
uint32_t location_count;
} fs_locations4;
typedef struct __nfs41_file_info {
nfs41_fsid fsid;
nfstime4 time_access;
nfstime4 time_create;
nfstime4 time_modify;
bitmap4 attrmask;
bitmap4 *supported_attrs; /* XXX: per-fs */
uint64_t maxread; /* XXX: per-fs */
uint64_t maxwrite; /* XXX: per-fs */
uint64_t change;
uint64_t size;
uint64_t fileid;
uint64_t space_avail; /* XXX: per-fs */
uint64_t space_free; /* XXX: per-fs */
uint64_t space_total; /* XXX: per-fs */
uint32_t type;
uint32_t numlinks;
uint32_t rdattr_error;
uint32_t mode;
uint32_t mode_mask;
fs_locations4 *fs_locations; /* XXX: per-fs */
uint32_t lease_time; /* XXX: per-server */
uint32_t fs_layout_types; /* pnfs, XXX: per-fs */
bool_t hidden;
} nfs41_file_info;
#endif /* !__NFS41_DAEMON_TYPES_H__ */

3124
daemon/nfs41_xdr.c Normal file

File diff suppressed because it is too large Load diff

33
daemon/nfs41_xdr.h Normal file
View file

@ -0,0 +1,33 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_NFS_XDR_H__
#define __NFS41_NFS_XDR_H__
#include "nfs41_types.h"
bool_t nfs_encode_compound(XDR *xdr, caddr_t *args);
bool_t nfs_decode_compound(XDR *xdr, caddr_t *res);
#endif /* !__NFS41_NFS_XDR_H__ */

445
daemon/open.c Normal file
View file

@ -0,0 +1,445 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include <strsafe.h>
#include "nfs41_ops.h"
#include "from_kernel.h"
#include "daemon_debug.h"
#include "upcall.h"
#include "util.h"
static int create_open_state(
IN const nfs41_abs_path *path,
IN uint32_t open_owner_id,
OUT nfs41_open_state **state_out)
{
int status;
nfs41_open_state *state;
state = calloc(1, sizeof(nfs41_open_state));
if (state == NULL) {
status = GetLastError();
goto out;
}
InitializeSRWLock(&state->path.lock);
abs_path_copy(&state->path, path);
path_fh_init(&state->file, &state->path);
path_fh_init(&state->parent, &state->path);
last_component(state->path.path, state->file.name.name,
&state->parent.name);
StringCchPrintfA((LPSTR)state->owner.owner, NFS4_OPAQUE_LIMIT,
"%u", open_owner_id);
state->owner.owner_len = (uint32_t)strlen(
(const char*)state->owner.owner);
*state_out = state;
status = NO_ERROR;
out:
return status;
}
static void free_open_state(
IN nfs41_session *session,
IN nfs41_open_state *state)
{
free(state);
}
/* NFS41_OPEN */
int parse_open(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
open_upcall_args *args = &upcall->args.open;
ZeroMemory(&args->path, sizeof(nfs41_abs_path));
status = get_abs_path(&buffer, &length, &args->path);
if (status) goto out;
status = safe_read(&buffer, &length, &args->access_mask, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->access_mode, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->file_attrs, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->create_opts, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->disposition, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->open_owner_id, sizeof(ULONG));
if (status) goto out;
status = safe_read(&buffer, &length, &args->mode, sizeof(DWORD));
out:
if (status)
eprintf("parsing NFS41_OPEN failed with %d\n", status);
else {
dprintf(1, "parsing NFS41_OPEN: filename='%s' access mask=%d "
"access mode=%d\n\tfile attrs=0x%x create attrs=0x%x "
"(kernel) disposition=%d\n\tsession=%p open_owner_id=%d mode=%o\n",
args->path.path, args->access_mask, args->access_mode, args->file_attrs,
args->create_opts, args->disposition, args->root, args->open_owner_id,
args->mode);
print_disposition(2, args->disposition);
print_access_mask(2, args->access_mask);
print_share_mode(2, args->access_mode);
print_create_attributes(2, args->create_opts);
}
return status;
}
static BOOLEAN do_lookup(uint32_t type, ULONG access_mask, ULONG disposition)
{
if (type == NF4DIR) {
if (disposition == FILE_OPEN || disposition == FILE_OVERWRITE) {
dprintf(1, "Opening a directory\n");
return TRUE;
} else {
dprintf(1, "Creating a directory\n");
return FALSE;
}
}
if ((access_mask & FILE_READ_DATA) ||
(access_mask & FILE_WRITE_DATA) ||
(access_mask & FILE_APPEND_DATA) ||
(access_mask & FILE_EXECUTE))
return FALSE;
else {
dprintf(1, "Open call that wants to manage attributes\n");
return TRUE;
}
}
static int map_disposition_2_nfsopen(ULONG disposition, int in_status,
uint32_t *create, uint32_t *last_error)
{
int status = NO_ERROR;
if (disposition == FILE_SUPERSEDE) {
if (in_status == NFS4ERR_NOENT) {
*create = OPEN4_CREATE;
*last_error = ERROR_FILE_NOT_FOUND;
}
else // we need to truncate the file file then open it
*create = OPEN4_NOCREATE;
} else if (disposition == FILE_CREATE) {
// if lookup succeeded which means the file exist, return an error
if (!in_status)
status = ERROR_FILE_EXISTS;
else
*create = OPEN4_CREATE;
} else if (disposition == FILE_OPEN) {
if (in_status == NFS4ERR_NOENT)
status = ERROR_FILE_NOT_FOUND;
else
*create = OPEN4_NOCREATE;
} else if (disposition == FILE_OPEN_IF) {
if (in_status == NFS4ERR_NOENT) {
dprintf(1, "creating new file\n");
*create = OPEN4_CREATE;
*last_error = ERROR_FILE_NOT_FOUND;
} else {
dprintf(1, "opening existing file\n");
*create = OPEN4_NOCREATE;
}
} else if (disposition == FILE_OVERWRITE) {
if (in_status == NFS4ERR_NOENT)
status = ERROR_FILE_NOT_FOUND;
//truncate file
*create = OPEN4_CREATE;
} else if (disposition == FILE_OVERWRITE_IF) {
if (in_status == NFS4ERR_NOENT)
*last_error = ERROR_FILE_NOT_FOUND;
//truncate file
*create = OPEN4_CREATE;
}
return status;
}
static int check_execute_access(nfs41_open_state *state)
{
uint32_t supported, access;
int status = nfs41_access(state->session, &state->file,
ACCESS4_EXECUTE | ACCESS4_READ, &supported, &access);
if (status) {
dprintf(1, "nfs41_access() failed with %s\n",
nfs_error_string(status));
status = ERROR_ACCESS_DENIED;
} else if ((supported & ACCESS4_EXECUTE) == 0) {
/* server can't verify execute access;
* for now, assume that read access is good enough */
if ((supported & ACCESS4_READ) == 0 || (access & ACCESS4_READ) == 0) {
dprintf(2, "server can't verify execute access, and user does "
"not have read access\n");
status = ERROR_ACCESS_DENIED;
}
} else if ((access & ACCESS4_EXECUTE) == 0) {
dprintf(2, "user does not have execute access to file\n");
status = ERROR_ACCESS_DENIED;
} else
dprintf(2, "user has execute access to file\n");
return status;
}
int handle_open(nfs41_upcall *upcall)
{
int status = 0;
open_upcall_args *args = &upcall->args.open;
nfs41_open_state *state;
bitmap4 attr_request;
nfs41_file_info info;
init_getattr_request(&attr_request);
status = create_open_state(&args->path, args->open_owner_id, &state);
if (status) {
eprintf("create_open_state(%u) failed with %d\n",
args->open_owner_id, status);
goto out;
}
// first check if windows told us it's a directory
if (args->create_opts & FILE_DIRECTORY_FILE)
state->type = NF4DIR;
else
state->type = NF4REG;
// always do a lookup
status = nfs41_lookup(args->root, nfs41_root_session(args->root),
&state->path, &state->parent, &state->file, &info, &state->session);
// now if file/dir exists, use type returned by lookup
if (status == NO_ERROR) {
if (info.type == NF4DIR) {
dprintf(2, "handle_nfs41_open: DIRECTORY\n");
if (args->create_opts & FILE_NON_DIRECTORY_FILE) {
eprintf("trying to open directory %s as a file\n",
args->path.path);
status = ERROR_ACCESS_DENIED;
goto out_free_state;
}
} else if (info.type == NF4REG) {
dprintf(2, "handle nfs41_open: FILE\n");
if (args->create_opts & FILE_DIRECTORY_FILE) {
eprintf("trying to open file %s as a directory\n",
args->path.path);
#ifdef NOTEPAD_OPEN_FILE_AS_DIRFILE_FIXED
status = ERROR_ACCESS_DENIED;
goto out_free_state;
#endif
}
} else
dprintf(2, "handle nfs41_open: is it SYMLINK?\n");
state->type = info.type;
} else if (status != ERROR_FILE_NOT_FOUND)
goto out_free_state;
if (do_lookup(state->type, args->access_mask, args->disposition)) {
if (status) {
dprintf(1, "nfs41_lookup failed with %d\n", status);
goto out_free_state;
}
nfs_to_basic_info(&info, &args->basic_info);
nfs_to_standard_info(&info, &args->std_info);
args->mode = info.mode;
args->changeattr = info.change;
} else {
uint32_t allow = 0, deny = 0, create = 0;
map_access_2_allowdeny(args->access_mask, args->access_mode, &allow, &deny);
status = map_disposition_2_nfsopen(args->disposition, status, &create, &upcall->last_error);
if (status)
goto out_free_state;
if (args->access_mask & FILE_EXECUTE && state->file.fh.len) {
status = check_execute_access(state);
if (status)
goto out_free_state;
}
if (create == OPEN4_CREATE && (args->create_opts & FILE_DIRECTORY_FILE)) {
status = nfs41_create(state->session, NF4DIR, args->mode,
&state->parent, &state->file);
args->std_info.Directory = 1;
args->created = status == NFS4_OK;
} else {
status = nfs41_open(state->session, allow, deny, create,
args->mode, state, &info);
if (status == NFS4_OK) {
nfs_to_basic_info(&info, &args->basic_info);
nfs_to_standard_info(&info, &args->std_info);
state->do_close = 1;
args->mode = info.mode;
}
}
if (status) {
dprintf(1, "%s failed with %s\n", (create == OPEN4_CREATE &&
(args->create_opts & FILE_DIRECTORY_FILE))?"nfs41_create":"nfs41_open",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
goto out_free_state;
}
}
args->state = state;
out:
return status;
out_free_state:
free(state);
goto out;
}
int marshall_open(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
int status;
open_upcall_args *args = &upcall->args.open;
status = safe_write(&buffer, length, &args->basic_info, sizeof(args->basic_info));
if (status) goto out;
status = safe_write(&buffer, length, &args->std_info, sizeof(args->std_info));
if (status) goto out;
status = safe_write(&buffer, length, &args->state, sizeof(args->state));
if (status) goto out;
status = safe_write(&buffer, length, &args->mode, sizeof(args->mode));
if (status) goto out;
status = safe_write(&buffer, length, &args->changeattr, sizeof(args->changeattr));
dprintf(2, "NFS41_OPEN: passing open_state=0x%p mode %o changeattr 0x%x\n",
args->state, args->mode, args->changeattr);
out:
return status;
}
int cancel_open(IN nfs41_upcall *upcall)
{
int status = NFS4_OK;
open_upcall_args *args = &upcall->args.open;
nfs41_open_state *state = args->state;
dprintf(1, "--> cancel_open('%s')\n", args->path.path);
if (upcall->status)
goto out; /* if handle_open() failed, the state was already freed */
if (state->do_close) {
status = nfs41_close(state->session, state);
if (status)
dprintf(1, "cancel_open: nfs41_close() failed with %s\n",
nfs_error_string(status));
} else if (args->created) {
const nfs41_component *name = &state->file.name;
status = nfs41_remove(state->session, &state->parent, name);
if (status)
dprintf(1, "cancel_open: nfs41_remove() failed with %s\n",
nfs_error_string(status));
}
free_open_state(state->session, state);
out:
status = nfs_to_windows_error(status, ERROR_INTERNAL_ERROR);
dprintf(1, "<-- cancel_open() returning %d\n", status);
return status;
}
/* NFS41_CLOSE */
int parse_close(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
close_upcall_args *args = &upcall->args.close;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status) goto out;
status = safe_read(&buffer, &length, &args->state, sizeof(nfs41_open_state *));
if (status) goto out;
status = safe_read(&buffer, &length, &args->remove, sizeof(BOOLEAN));
if (status) goto out;
if (args->remove) {
ZeroMemory(&args->path, sizeof(nfs41_abs_path));
status = get_abs_path(&buffer, &length, &args->path);
if (status) goto out;
status = safe_read(&buffer, &length, &args->renamed, sizeof(BOOLEAN));
}
out:
if (status)
eprintf("parsing NFS41_CLOSE failed with %d\n", status);
else
dprintf(1, "parsing NFS41_CLOSE: close root=0x%p "
"open_state=0x%p remove=%d renamed=%d filename='%s'\n",
args->root, args->state, args->remove, args->renamed,
args->remove ? args->path.path : "");
return status;
}
int handle_close(nfs41_upcall *upcall)
{
int status = NFS4_OK, rm_status = NFS4_OK;
close_upcall_args *args = &upcall->args.close;
nfs41_open_state *state = args->state;
/* return associated file layouts if necessary */
if (state->type == NF4REG)
pnfs_open_state_close(state->session, state, args->remove);
if (args->remove) {
nfs41_component *name = &state->file.name;
if (args->renamed) {
dprintf(1, "removing a renamed file %s\n", name->name);
create_silly_rename(&state->path, &state->file.fh, name);
}
dprintf(1, "calling nfs41_remove for %s\n", name->name);
rm_status = nfs41_remove(state->session, &state->parent, name);
if (rm_status) {
dprintf(1, "nfs41_remove() failed with error %s.\n",
nfs_error_string(rm_status));
rm_status = nfs_to_windows_error(rm_status, ERROR_INTERNAL_ERROR);
}
}
if (state->do_close) {
status = nfs41_close(state->session, state);
if (status) {
dprintf(1, "nfs41_close() failed with error %s.\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_INTERNAL_ERROR);
}
}
if (args->state->type == NF4REG || !args->remove)
free_open_state(state->session, state);
if (status || !rm_status)
return status;
else
return rm_status;
}
int marshall_close(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
return NO_ERROR;
}

352
daemon/pnfs.h Normal file
View file

@ -0,0 +1,352 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __PNFS_H__
#define __PNFS_H__
#include "nfs41_types.h"
#include "list.h"
/* preprocessor options */
#ifndef PNFS_DISABLE
# ifndef PNFS_DISABLE_READ
# define PNFS_ENABLE_READ
# endif
# ifndef PNFS_DISABLE_WRITE
# define PNFS_ENABLE_WRITE
# endif
# define PNFS_THREADING
# define PNFS_THREAD_BY_SERVER
#endif
/* forward declarations from nfs41.h */
struct __nfs41_client;
struct __nfs41_session;
struct __nfs41_open_state;
struct __nfs41_root;
/* pnfs error values, in order of increasing severity */
enum pnfs_status {
PNFS_SUCCESS = 0,
PNFS_PENDING,
PNFS_READ_EOF,
PNFSERR_NOT_SUPPORTED,
PNFSERR_NOT_CONNECTED,
PNFSERR_IO,
PNFSERR_NO_DEVICE,
PNFSERR_NO_LAYOUT,
PNFSERR_INVALID_FH_LIST,
PNFSERR_INVALID_DS_INDEX,
PNFSERR_RESOURCES,
PNFSERR_LAYOUT_RECALLED,
PNFSERR_LAYOUT_CHANGED,
};
enum pnfs_layout_type {
PNFS_LAYOUTTYPE_FILE = 1,
PNFS_LAYOUTTYPE_OBJECT = 2,
PNFS_LAYOUTTYPE_BLOCK = 3
};
enum pnfs_iomode {
PNFS_IOMODE_READ = 0x1,
PNFS_IOMODE_RW = 0x2,
PNFS_IOMODE_ANY = PNFS_IOMODE_READ | PNFS_IOMODE_RW
};
enum pnfs_layout_status {
/* LAYOUTGET was successful, and the layout has not been returned or
* otherwise revoked by the server */
PNFS_LAYOUT_GRANTED = 0x01,
/* GETDEVICEINFO was successful, and we have a valid 'device' pointer */
PNFS_LAYOUT_HAS_DEVICE = 0x02,
/* CB_LAYOUTRECALL indicated that the server has recalled this layout,
* and it should be returned on completion of any pending io */
PNFS_LAYOUT_RECALLED = 0x04,
/* CB_LAYOUTRECALL indicated that the layout is changing, and "the client
* SHOULD NOT write and commit modified data to the storage devices!" */
PNFS_LAYOUT_CHANGED = 0x08,
/* a LAYOUTGET error indicated that this layout will never be granted */
PNFS_LAYOUT_UNAVAILABLE = 0x10,
/* LAYOUTGET returned BADIOMODE, so a RW layout will never be granted */
PNFS_LAYOUT_NOT_RW = 0x20,
};
enum pnfs_return_type {
PNFS_RETURN_FILE = 1,
PNFS_RETURN_FSID = 2,
PNFS_RETURN_ALL = 3
};
#define NFL4_UFLG_MASK 0x0000003F
#define NFL4_UFLG_DENSE 0x00000001
#define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002
#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK 0xFFFFFFC0
#define PNFS_DEVICEID_SIZE 16
/* device */
typedef struct __pnfs_device {
unsigned char deviceid[PNFS_DEVICEID_SIZE];
enum pnfs_layout_type type;
} pnfs_device;
typedef struct __pnfs_stripe_indices {
uint32_t count;
uint32_t *arr;
} pnfs_stripe_indices;
typedef struct __pnfs_data_server {
struct __nfs41_client *client;
multi_addr4 addrs;
SRWLOCK lock;
} pnfs_data_server;
typedef struct __pnfs_data_server_list {
uint32_t count;
pnfs_data_server *arr;
} pnfs_data_server_list;
typedef struct __pnfs_file_device {
pnfs_device device;
pnfs_stripe_indices stripes;
pnfs_data_server_list servers;
struct list_entry entry; /* position in nfs41_client.devices */
SRWLOCK lock;
} pnfs_file_device;
/* layout */
typedef struct __pnfs_layout {
stateid4 state;
uint64_t offset;
uint64_t length;
enum pnfs_layout_type type;
enum pnfs_iomode iomode;
enum pnfs_layout_status status;
bool_t return_on_close;
uint32_t io_count; /* number of pending io operations */
SRWLOCK lock;
} pnfs_layout;
typedef struct __pnfs_file_layout_handles {
uint32_t count;
nfs41_path_fh *arr;
} pnfs_file_layout_handles;
typedef struct __pnfs_file_layout {
pnfs_layout layout;
pnfs_file_layout_handles filehandles;
unsigned char deviceid[PNFS_DEVICEID_SIZE];
struct list_entry entry; /* position in nfs41_client.layouts */
pnfs_file_device *device;
nfs41_fh meta_fh;
uint64_t pattern_offset;
uint32_t first_index;
uint32_t util;
} pnfs_file_layout;
typedef struct __pnfs_layout_recall {
enum pnfs_layout_type type;
enum pnfs_iomode iomode;
bool_t changed;
enum pnfs_return_type recall;
union {
struct {
nfs41_fh fh;
stateid4 stateid;
} file;
nfs41_fsid fsid;
} args;
} pnfs_layout_recall;
/* io */
typedef struct __pnfs_io_pattern {
struct __pnfs_io_thread *threads;
struct __nfs41_root *root;
nfs41_path_fh *meta_file;
stateid4 *stateid;
pnfs_file_layout *layout;
unsigned char *buffer;
uint64_t offset_start;
uint64_t offset_end;
uint32_t count;
uint32_t default_lease;
} pnfs_io_pattern;
typedef struct __pnfs_io_thread {
pnfs_io_pattern *pattern;
uint64_t offset;
uint64_t offset_end;
uint32_t id;
enum stable_how4 stable;
} pnfs_io_thread;
typedef struct __pnfs_io_unit {
nfs41_path_fh *file;
unsigned char *buffer;
uint64_t offset;
uint64_t length;
uint32_t stripeid;
uint32_t serverid;
} pnfs_io_unit;
typedef uint32_t (WINAPI *pnfs_io_thread_fn)(void*);
/* pnfs_layout.c */
struct pnfs_file_layout_list;
struct cb_layoutrecall_args;
enum pnfs_status pnfs_file_layout_list_create(
OUT struct pnfs_file_layout_list **layouts_out);
void pnfs_file_layout_list_free(
IN struct pnfs_file_layout_list *layouts);
enum pnfs_status pnfs_open_state_layout(
IN struct pnfs_file_layout_list *layouts,
IN struct __nfs41_session *session,
IN struct __nfs41_open_state *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length,
OUT pnfs_file_layout **layout_out);
void pnfs_open_state_close(
IN struct __nfs41_session *session,
IN struct __nfs41_open_state *state,
IN bool_t remove);
enum pnfs_status pnfs_file_layout_recall(
IN struct pnfs_file_layout_list *layouts,
IN const struct cb_layoutrecall_args *recall);
enum pnfs_status pnfs_layout_io_start(
IN pnfs_layout *layout);
void pnfs_layout_io_finished(
IN pnfs_layout *layout);
__inline int is_dense(
IN const pnfs_file_layout *layout)
{
return (layout->util & NFL4_UFLG_DENSE) != 0;
}
__inline int should_commit_to_mds(
IN const pnfs_file_layout *layout)
{
return (layout->util & NFL4_UFLG_COMMIT_THRU_MDS) != 0;
}
__inline uint32_t layout_unit_size(
IN const pnfs_file_layout *layout)
{
return layout->util & NFL4_UFLG_STRIPE_UNIT_SIZE_MASK;
}
/* pnfs_device.c */
struct pnfs_file_device_list;
enum pnfs_status pnfs_file_device_list_create(
OUT struct pnfs_file_device_list **devices_out);
void pnfs_file_device_list_free(
IN struct pnfs_file_device_list *devices);
enum pnfs_status pnfs_file_device_get(
IN struct __nfs41_session *session,
IN struct pnfs_file_device_list *devices,
IN unsigned char *deviceid,
OUT pnfs_file_device **device_out);
enum pnfs_status pnfs_data_server_client(
IN struct __nfs41_root *root,
IN pnfs_data_server *server,
IN uint32_t default_lease,
OUT struct __nfs41_client **client_out);
enum pnfs_status pnfs_file_device_io_unit(
IN pnfs_io_pattern *pattern,
IN uint64_t offset,
OUT pnfs_io_unit *io);
__inline uint64_t stripe_unit_number(
IN pnfs_file_layout *layout,
IN uint64_t offset,
IN uint32_t unit_size)
{
const uint64_t relative_offset = offset - layout->pattern_offset;
return relative_offset / unit_size;
}
__inline uint32_t stripe_index(
IN pnfs_file_layout *layout,
IN uint64_t sui,
IN uint32_t stripe_count)
{
return (sui + layout->first_index) % stripe_count;
}
__inline uint32_t data_server_index(
IN pnfs_file_device *device,
IN uint32_t stripeid)
{
return device->stripes.arr[stripeid];
}
/* pnfs_io.c */
enum pnfs_status pnfs_read(
IN struct __nfs41_root *root,
IN struct __nfs41_session *session,
IN nfs41_path_fh *file,
IN stateid4 *stateid,
IN pnfs_file_layout *layout,
IN uint64_t offset,
IN uint64_t length,
OUT unsigned char *buffer_out,
OUT ULONG *len_out);
enum pnfs_status pnfs_write(
IN struct __nfs41_root *root,
IN struct __nfs41_session *session,
IN nfs41_path_fh *file,
IN stateid4 *stateid,
IN pnfs_file_layout *layout,
IN uint64_t offset,
IN uint64_t length,
IN unsigned char *buffer,
OUT ULONG *len_out);
#endif /* !__PNFS_H__ */

125
daemon/pnfs_debug.c Normal file
View file

@ -0,0 +1,125 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <winsock2.h>
#include <strsafe.h>
#include "pnfs.h"
#include "daemon_debug.h"
const char* pnfs_error_string(enum pnfs_status status)
{
switch (status) {
case PNFS_SUCCESS: return "PNFS_SUCCESS";
case PNFS_PENDING: return "PNFS_PENDING";
case PNFS_READ_EOF: return "PNFS_READ_EOF";
case PNFSERR_NOT_SUPPORTED: return "PNFSERR_NOT_SUPPORTED";
case PNFSERR_NOT_CONNECTED: return "PNFSERR_NOT_CONNECTED";
case PNFSERR_IO: return "PNFSERR_IO";
case PNFSERR_NO_DEVICE: return "PNFSERR_NO_DEVICE";
case PNFSERR_NO_LAYOUT: return "PNFSERR_NO_LAYOUT";
case PNFSERR_INVALID_FH_LIST: return "PNFSERR_INVALID_FH_LIST";
case PNFSERR_INVALID_DS_INDEX: return "PNFSERR_INVALID_DS_INDEX";
case PNFSERR_RESOURCES: return "PNFSERR_RESOURCES";
case PNFSERR_LAYOUT_RECALLED: return "PNFSERR_LAYOUT_RECALLED";
case PNFSERR_LAYOUT_CHANGED: return "PNFSERR_LAYOUT_CHANGED";
default: return "Invalid pnfs status";
}
}
const char* pnfs_layout_type_string(enum pnfs_layout_type type)
{
switch (type) {
case PNFS_LAYOUTTYPE_FILE: return "PNFS_LAYOUTTYPE_FILE";
case PNFS_LAYOUTTYPE_OBJECT: return "PNFS_LAYOUTTYPE_OBJECT";
case PNFS_LAYOUTTYPE_BLOCK: return "PNFS_LAYOUTTYPE_BLOCK";
default: return "Invalid layout type";
}
}
const char* pnfs_iomode_string(enum pnfs_iomode iomode)
{
switch (iomode) {
case PNFS_IOMODE_READ: return "PNFS_IOMODE_READ";
case PNFS_IOMODE_RW: return "PNFS_IOMODE_RW";
case PNFS_IOMODE_ANY: return "PNFS_IOMODE_ANY";
default: return "Invalid io mode";
}
}
void dprint_deviceid(
IN int level,
IN const char *title,
IN const unsigned char *deviceid)
{
/* deviceid is 16 bytes, so print it as 4 uints */
uint32_t *p = (uint32_t*)deviceid;
dprintf(level, "%s%08X.%08X.%08X.%08X\n",
title, htonl(p[0]), htonl(p[1]), htonl(p[2]), htonl(p[3]));
}
void dprint_layout(
IN int level,
IN const pnfs_file_layout *layout)
{
dprintf(level, " type: %s\n", pnfs_layout_type_string(layout->layout.type));
dprintf(level, " iomode: %s\n", pnfs_iomode_string(layout->layout.iomode));
dprint_deviceid(level, " deviceid: ", layout->deviceid);
dprintf(level, " offset: %llu\n", layout->layout.offset);
dprintf(level, " length: %llu\n", layout->layout.length);
dprintf(level, " pattern_offset: %llu\n", layout->pattern_offset);
dprintf(level, " first_index: %u\n", layout->first_index);
dprintf(level, " dense: %u\n", is_dense(layout));
dprintf(level, " commit_to_mds: %u\n", should_commit_to_mds(layout));
dprintf(level, " stripe_unit_size: %u\n", layout_unit_size(layout));
dprintf(level, " file handles: %u\n", layout->filehandles.count);
}
#define MULTI_ADDR_BUFFER_LEN \
(NFS41_ADDRS_PER_SERVER*(NFS41_UNIVERSAL_ADDR_LEN+1)+1)
static void dprint_multi_addr(
IN int level,
IN uint32_t index,
IN const multi_addr4 *addrs)
{
char buffer[MULTI_ADDR_BUFFER_LEN] = "";
uint32_t i;
for (i = 0; i < addrs->count; i++) {
StringCchCatA(buffer, MULTI_ADDR_BUFFER_LEN, addrs->arr[i].uaddr);
StringCchCatA(buffer, MULTI_ADDR_BUFFER_LEN, " ");
}
dprintf(level, " servers[%d]: [ %s]\n", index, buffer);
}
void dprint_device(
IN int level,
IN const pnfs_file_device *device)
{
uint32_t i;
dprint_deviceid(level, " deviceid: ", device->device.deviceid);
dprintf(level, " type: %s\n", pnfs_layout_type_string(device->device.type));
dprintf(level, " stripes: %u\n", device->stripes.count);
for (i = 0; i < device->servers.count; i++)
dprint_multi_addr(level, i, &device->servers.arr[i].addrs);
}

376
daemon/pnfs_device.c Normal file
View file

@ -0,0 +1,376 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include <stdio.h>
#include "nfs41_ops.h"
#include "daemon_debug.h"
#define FDLVL 2 /* dprintf level for file device logging */
/* pnfs_file_device_list */
struct pnfs_file_device_list {
struct list_entry head;
CRITICAL_SECTION lock;
};
#define device_entry(pos) list_container(pos, pnfs_file_device, entry)
static enum pnfs_status file_device_create(
IN const unsigned char *deviceid,
OUT pnfs_file_device **device_out)
{
enum pnfs_status status = PNFS_SUCCESS;
pnfs_file_device *device;
device = calloc(1, sizeof(pnfs_file_device));
if (device == NULL) {
status = PNFSERR_RESOURCES;
goto out;
}
memcpy(device->device.deviceid, deviceid, PNFS_DEVICEID_SIZE);
InitializeSRWLock(&device->lock);
*device_out = device;
out:
return status;
}
static void file_device_free(
IN pnfs_file_device *device)
{
free(device->servers.arr);
free(device->stripes.arr);
free(device);
}
static int deviceid_compare(
const struct list_entry *entry,
const void *deviceid)
{
const pnfs_file_device *device = device_entry(entry);
return memcmp(device->device.deviceid, deviceid, PNFS_DEVICEID_SIZE);
}
static enum pnfs_status file_device_entry_find(
IN struct pnfs_file_device_list *devices,
IN const unsigned char *deviceid,
OUT struct list_entry **entry_out)
{
*entry_out = list_search(&devices->head, deviceid, deviceid_compare);
return *entry_out ? PNFS_SUCCESS : PNFSERR_NO_DEVICE;
}
static enum pnfs_status file_device_find_or_create(
IN const unsigned char *deviceid,
IN struct pnfs_file_device_list *devices,
OUT pnfs_file_device **device_out)
{
struct list_entry *entry;
enum pnfs_status status;
dprintf(FDLVL, "--> pnfs_file_device_find_or_create()\n");
EnterCriticalSection(&devices->lock);
/* search for an existing device */
status = file_device_entry_find(devices, deviceid, &entry);
if (status) {
/* create a new device */
pnfs_file_device *device;
status = file_device_create(deviceid, &device);
if (status == PNFS_SUCCESS) {
/* add it to the list */
list_add_tail(&devices->head, &device->entry);
*device_out = device;
dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
"returning new device %p\n", device);
} else {
dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
"returning %s\n", pnfs_error_string(status));
}
} else {
*device_out = device_entry(entry);
dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
"returning existing device %p\n", *device_out);
}
LeaveCriticalSection(&devices->lock);
return status;
}
enum pnfs_status pnfs_file_device_list_create(
OUT struct pnfs_file_device_list **devices_out)
{
enum pnfs_status status = PNFS_SUCCESS;
struct pnfs_file_device_list *devices;
devices = calloc(1, sizeof(struct pnfs_file_device_list));
if (devices == NULL) {
status = PNFSERR_RESOURCES;
goto out;
}
list_init(&devices->head);
InitializeCriticalSection(&devices->lock);
*devices_out = devices;
out:
return status;
}
void pnfs_file_device_list_free(
IN struct pnfs_file_device_list *devices)
{
struct list_entry *entry, *tmp;
EnterCriticalSection(&devices->lock);
list_for_each_tmp(entry, tmp, &devices->head)
file_device_free(device_entry(entry));
LeaveCriticalSection(&devices->lock);
free(devices);
}
/* pnfs_file_device */
static enum pnfs_status file_device_status(
IN pnfs_file_device *device)
{
return device->device.type == 0 ? PNFS_PENDING : PNFS_SUCCESS;
}
enum pnfs_status pnfs_file_device_get(
IN nfs41_session *session,
IN struct pnfs_file_device_list *devices,
IN unsigned char *deviceid,
OUT pnfs_file_device **device_out)
{
pnfs_file_device *device;
enum pnfs_status status;
enum nfsstat4 nfsstat;
dprintf(FDLVL, "--> pnfs_file_device_get()\n");
status = file_device_find_or_create(deviceid, devices, &device);
if (status)
goto out;
AcquireSRWLockShared(&device->lock);
status = file_device_status(device);
ReleaseSRWLockShared(&device->lock);
if (status == PNFS_PENDING) {
AcquireSRWLockExclusive(&device->lock);
status = file_device_status(device);
if (status == PNFS_PENDING) {
nfsstat = pnfs_rpc_getdeviceinfo(session, deviceid, device);
if (nfsstat == NFS4_OK) {
status = PNFS_SUCCESS;
dprintf(FDLVL, "Received device info:\n");
dprint_device(FDLVL, device);
} else {
status = PNFSERR_NO_DEVICE;
eprintf("pnfs_rpc_getdeviceinfo() failed with %s\n",
nfs_error_string(nfsstat));
}
}
ReleaseSRWLockExclusive(&device->lock);
}
*device_out = device;
out:
dprintf(FDLVL, "<-- pnfs_file_device_get() returning %s\n",
pnfs_error_string(status));
return status;
}
static enum pnfs_status data_client_status(
IN pnfs_data_server *server,
OUT nfs41_client **client_out)
{
enum pnfs_status status = PNFSERR_NOT_CONNECTED;
if (server->client) {
dprintf(FDLVL, "pnfs_data_server_client() returning "
"existing client %llu\n", server->client->clnt_id);
*client_out = server->client;
status = PNFS_SUCCESS;
}
return status;
}
enum pnfs_status pnfs_data_server_client(
IN nfs41_root *root,
IN pnfs_data_server *server,
IN uint32_t default_lease,
OUT nfs41_client **client_out)
{
int status;
enum pnfs_status pnfsstat;
dprintf(FDLVL, "--> pnfs_data_server_client('%s')\n",
server->addrs.arr[0].uaddr);
/* if we've already created the client, return it */
AcquireSRWLockShared(&server->lock);
pnfsstat = data_client_status(server, client_out);
ReleaseSRWLockShared(&server->lock);
if (pnfsstat) {
AcquireSRWLockExclusive(&server->lock);
pnfsstat = data_client_status(server, client_out);
if (pnfsstat) {
status = nfs41_root_mount_addrs(root, &server->addrs,
1, default_lease, &server->client);
if (status) {
dprintf(FDLVL, "data_client_create('%s') failed with %d\n",
server->addrs.arr[0].uaddr, status);
} else {
*client_out = server->client;
pnfsstat = PNFS_SUCCESS;
dprintf(FDLVL, "pnfs_data_server_client() returning "
"new client %llu\n", server->client->clnt_id);
}
}
ReleaseSRWLockExclusive(&server->lock);
}
return pnfsstat;
}
/* 13.4.2. Interpreting the File Layout Using Sparse Packing
* http://tools.ietf.org/html/rfc5661#section-13.4.2 */
static enum pnfs_status get_sparse_fh(
IN pnfs_io_pattern *pattern,
IN uint32_t stripeid,
OUT nfs41_path_fh **file_out)
{
pnfs_file_layout *layout = pattern->layout;
const uint32_t filehandle_count = layout->filehandles.count;
const uint32_t server_count = layout->device->servers.count;
enum pnfs_status status = PNFS_SUCCESS;
if (filehandle_count == server_count) {
const uint32_t serverid = data_server_index(layout->device, stripeid);
*file_out = &layout->filehandles.arr[serverid];
} else if (filehandle_count == 1) {
*file_out = &layout->filehandles.arr[0];
} else if (filehandle_count == 0) {
*file_out = pattern->meta_file;
} else {
eprintf("invalid sparse layout! has %u file handles "
"and %u servers\n", filehandle_count, server_count);
status = PNFSERR_INVALID_FH_LIST;
}
return status;
}
/* 13.4.3. Interpreting the File Layout Using Dense Packing
* http://tools.ietf.org/html/rfc5661#section-13.4.3 */
static enum pnfs_status get_dense_fh(
IN pnfs_io_pattern *pattern,
IN uint32_t stripeid,
OUT nfs41_path_fh **file_out)
{
pnfs_file_layout *layout = pattern->layout;
const uint32_t filehandle_count = layout->filehandles.count;
const uint32_t stripe_count = layout->device->stripes.count;
enum pnfs_status status = PNFS_SUCCESS;
if (filehandle_count == stripe_count) {
*file_out = &layout->filehandles.arr[stripeid];
} else {
eprintf("invalid dense layout! has %u file handles "
"and %u stripes\n", filehandle_count, stripe_count);
status = PNFSERR_INVALID_FH_LIST;
}
return status;
}
static __inline uint64_t positive_remainder(
IN uint64_t dividend,
IN uint32_t divisor)
{
const uint64_t remainder = dividend % divisor;
return remainder < divisor ? remainder : remainder + divisor;
}
/* 13.4.4. Sparse and Dense Stripe Unit Packing
* http://tools.ietf.org/html/rfc5661#section-13.4.4 */
enum pnfs_status pnfs_file_device_io_unit(
IN pnfs_io_pattern *pattern,
IN uint64_t offset,
OUT pnfs_io_unit *io)
{
pnfs_file_layout *layout = pattern->layout;
enum pnfs_status status = PNFS_SUCCESS;
const uint32_t unit_size = layout_unit_size(layout);
const uint32_t stripe_count = layout->device->stripes.count;
const uint64_t sui = stripe_unit_number(layout, offset, unit_size);
const uint64_t offset_end = layout->pattern_offset + unit_size * (sui + 1);
io->stripeid = stripe_index(layout, sui, stripe_count);
io->serverid = data_server_index(layout->device, io->stripeid);
if (is_dense(layout)) {
const uint64_t rel_offset = offset - layout->pattern_offset;
const uint64_t remainder = positive_remainder(rel_offset, unit_size);
const uint32_t stride = unit_size * stripe_count;
io->offset = (rel_offset / stride) * unit_size + remainder;
status = get_dense_fh(pattern, io->stripeid, &io->file);
} else {
io->offset = offset;
status = get_sparse_fh(pattern, io->stripeid, &io->file);
}
io->buffer = pattern->buffer + offset - pattern->offset_start;
io->length = offset_end - offset;
if (offset + io->length > pattern->offset_end)
io->length = pattern->offset_end - offset;
return status;
}

565
daemon/pnfs_io.c Normal file
View file

@ -0,0 +1,565 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <stdio.h>
#include <process.h>
#include "nfs41_ops.h"
#include "util.h"
#include "daemon_debug.h"
#define IOLVL 2 /* dprintf level for pnfs io logging */
static uint32_t io_unit_count(
const pnfs_file_layout *layout,
uint64_t length)
{
const uint32_t unit_size = layout_unit_size(layout);
return (uint32_t)(length / unit_size) + (length % unit_size ? 1 : 0);
}
static enum pnfs_status pattern_init(
IN pnfs_io_pattern *pattern,
IN nfs41_root *root,
IN nfs41_path_fh *meta_file,
IN stateid4 *stateid,
IN pnfs_file_layout *layout,
IN unsigned char *buffer,
IN uint64_t offset,
IN uint64_t length,
IN uint32_t default_lease)
{
#ifndef PNFS_THREAD_BY_SERVER
pnfs_io_unit io;
#endif
uint64_t pos;
uint32_t i;
enum pnfs_status status;
/* take a reference on the layout so we don't return it during io */
status = pnfs_layout_io_start(&layout->layout);
if (status)
goto out;
#ifdef PNFS_THREAD_BY_SERVER
pattern->count = layout->device->servers.count;
#else
pattern->count = io_unit_count(layout, length);
#endif
pattern->threads = calloc(pattern->count, sizeof(pnfs_io_thread));
if (pattern->threads == NULL) {
status = PNFSERR_RESOURCES;
free(pattern);
goto out;
}
pattern->root = root;
pattern->meta_file = meta_file;
pattern->stateid = stateid;
pattern->layout = layout;
pattern->buffer = buffer;
pattern->offset_start = offset;
pattern->offset_end = offset + length;
pattern->default_lease = default_lease;
pos = pattern->offset_start;
for (i = 0; i < pattern->count; i++) {
pattern->threads[i].pattern = pattern;
pattern->threads[i].stable = DATA_SYNC4;
#ifdef PNFS_THREAD_BY_SERVER
pattern->threads[i].offset = pattern->offset_start;
pattern->threads[i].offset_end = pattern->offset_end;
pattern->threads[i].id = i;
#else
pnfs_file_device_io_unit(pattern, pos, &io);
pattern->threads[i].offset = pos;
pattern->threads[i].offset_end = pos += io.length;
pattern->threads[i].id = io.stripeid;
if (pattern->threads[i].offset > pattern->offset_end)
pattern->threads[i].offset = pattern->offset_end;
if (pattern->threads[i].offset_end > pattern->offset_end)
pattern->threads[i].offset_end = pattern->offset_end;
dprintf(IOLVL, "io_unit(off=%llu end=%llu id=%u)\n",
pattern->threads[i].offset,
pattern->threads[i].offset_end,
pattern->threads[i].id);
#endif
}
out:
return status;
}
static void pattern_free(
IN pnfs_io_pattern *pattern)
{
/* inform the layout that our io is finished */
pnfs_layout_io_finished(&pattern->layout->layout);
free(pattern->threads);
}
static enum pnfs_status thread_next_unit(
IN pnfs_io_thread *thread,
OUT pnfs_io_unit *io)
{
pnfs_io_pattern *pattern = thread->pattern;
pnfs_file_layout *layout = pattern->layout;
enum pnfs_status status = PNFS_SUCCESS;
AcquireSRWLockShared(&layout->layout.lock);
/* stop io if the layout is recalled */
if (layout->layout.status & PNFS_LAYOUT_CHANGED) {
status = PNFSERR_LAYOUT_CHANGED;
goto out_unlock;
}
if (layout->layout.status & PNFS_LAYOUT_RECALLED) {
status = PNFSERR_LAYOUT_RECALLED;
goto out_unlock;
}
/* loop until we find an io unit that matches this thread */
while (thread->offset < thread->offset_end) {
pnfs_file_device_io_unit(pattern, thread->offset, io);
#ifdef PNFS_THREAD_BY_SERVER
if (io->serverid == thread->id) {
#else
if (io->stripeid == thread->id) {
#endif
status = PNFS_PENDING;
break;
}
thread->offset += io->length;
}
out_unlock:
ReleaseSRWLockShared(&layout->layout.lock);
return status;
}
static enum pnfs_status thread_data_server(
IN pnfs_io_thread *thread,
OUT pnfs_data_server **server_out)
{
pnfs_file_device *device = thread->pattern->layout->device;
#ifdef PNFS_THREAD_BY_SERVER
const uint32_t serverid = thread->id;
#else
const uint32_t serverid = data_server_index(device, thread->id);
#endif
if (serverid >= device->servers.count)
return PNFSERR_INVALID_DS_INDEX;
*server_out = &device->servers.arr[serverid];
return PNFS_SUCCESS;
}
static enum pnfs_status pattern_fork(
IN pnfs_io_pattern *pattern,
IN pnfs_io_thread_fn thread_fn)
{
pnfs_io_unit io;
#ifdef PNFS_THREADING
HANDLE *threads;
uint32_t num_threads;
#endif
uint32_t i;
DWORD status;
enum pnfs_status pnfsstat = PNFS_SUCCESS;
if (pattern->count == 0)
goto out;
#ifdef PNFS_THREADING
/* create a thread for each unit that has actual io */
threads = calloc(pattern->count, sizeof(HANDLE));
if (threads == NULL) {
pnfsstat = PNFSERR_RESOURCES;
goto out;
}
num_threads = 0;
for (i = 0; i < pattern->count; i++) {
if (thread_next_unit(&pattern->threads[i], &io) == PNFS_PENDING) {
threads[num_threads++] = (HANDLE)_beginthreadex(NULL, 0,
thread_fn, &pattern->threads[i], 0, NULL);
}
}
if (num_threads) { /* wait on all threads to finish */
status = WaitForMultipleObjects(num_threads, threads, TRUE, INFINITE);
if (status == WAIT_OBJECT_0)
status = NO_ERROR;
for (i = 0; i < num_threads; i++) {
/* keep track of the most severe error returned by a thread */
if (GetExitCodeThread(threads[i], &status))
pnfsstat = max(pnfsstat, (enum pnfs_status)status);
CloseHandle(threads[i]);
}
}
free(threads);
#else
/* process each server that has actual io */
for (i = 0; i < pattern->count; i++) {
if (thread_next_unit(&pattern->threads[i], &io) == PNFS_PENDING) {
/* keep track of the most severe error returned by a thread */
status = thread_fn(&pattern->threads[i]);
pnfsstat = max(pnfsstat, (enum pnfs_status)status);
}
}
#endif
out:
return pnfsstat;
}
static uint64_t pattern_bytes_transferred(
IN pnfs_io_pattern *pattern,
OUT OPTIONAL enum stable_how4 *stable)
{
uint64_t lowest_offset = pattern->offset_end;
uint32_t i;
if (stable) *stable = DATA_SYNC4;
for (i = 0; i < pattern->count; i++) {
if (lowest_offset > pattern->threads[i].offset)
lowest_offset = pattern->threads[i].offset;
if (stable && pattern->threads[i].stable == UNSTABLE4)
*stable = UNSTABLE4;
}
return lowest_offset - pattern->offset_start;
}
static enum pnfs_status map_ds_error(
IN enum nfsstat4 nfsstat,
IN pnfs_layout *layout)
{
switch (nfsstat) {
case NO_ERROR:
return PNFS_SUCCESS;
/* 13.11 Layout Revocation and Fencing
* http://tools.ietf.org/html/rfc5661#section-13.11
* if we've been fenced, we'll either get ERR_STALE when we PUTFH
* something in layout.filehandles, or ERR_PNFS_NO_LAYOUT when
* attempting to READ or WRITE */
case NFS4ERR_STALE:
case NFS4ERR_PNFS_NO_LAYOUT:
dprintf(IOLVL, "data server fencing detected!\n");
AcquireSRWLockExclusive(&layout->lock);
/* flag the layout for return once io is finished */
layout->status |= PNFS_LAYOUT_RECALLED | PNFS_LAYOUT_CHANGED;
/* reset GRANTED so we know not to try LAYOUTRETURN */
layout->status &= ~PNFS_LAYOUT_GRANTED;
ReleaseSRWLockExclusive(&layout->lock);
/* return CHANGED to prevent any further use of the layout */
return PNFSERR_LAYOUT_CHANGED;
default:
return PNFSERR_IO;
}
}
static uint32_t WINAPI file_layout_read_thread(void *args)
{
pnfs_io_unit io;
pnfs_io_thread *thread = (pnfs_io_thread*)args;
pnfs_io_pattern *pattern = thread->pattern;
stateid4 *state = pattern->stateid;
pnfs_data_server *server;
nfs41_client *client;
uint32_t maxreadsize, bytes_read, total_read;
enum pnfs_status status;
enum nfsstat4 nfsstat;
bool_t eof;
dprintf(IOLVL, "--> file_layout_read_thread(%u)\n", thread->id);
/* get the data server for this thread */
status = thread_data_server(thread, &server);
if (status) {
eprintf("thread_data_server() failed with %s\n",
pnfs_error_string(status));
goto out;
}
/* find or establish a client for this data server */
status = pnfs_data_server_client(pattern->root,
server, pattern->default_lease, &client);
if (status) {
eprintf("pnfs_data_server_client() failed with %s\n",
pnfs_error_string(status));
goto out;
}
total_read = 0;
while ((status = thread_next_unit(thread, &io)) == PNFS_PENDING) {
maxreadsize = max_read_size(client->session, &io.file->fh);
if (io.length > maxreadsize)
io.length = maxreadsize;
nfsstat = nfs41_read(client->session, io.file, state, io.offset,
(uint32_t)io.length, io.buffer, &bytes_read, &eof);
if (nfsstat) {
eprintf("nfs41_read() failed with %s\n",
nfs_error_string(nfsstat));
status = map_ds_error(nfsstat, &pattern->layout->layout);
break;
}
total_read += bytes_read;
thread->offset += bytes_read;
if (eof) {
dprintf(IOLVL, "read thread %u reached eof: offset %llu\n",
thread->id, thread->offset);
status = total_read ? PNFS_SUCCESS : PNFS_READ_EOF;
break;
}
}
out:
dprintf(IOLVL, "<-- file_layout_read_thread(%u) returning %s\n",
thread->id, pnfs_error_string(status));
return status;
}
static uint32_t WINAPI file_layout_write_thread(void *args)
{
pnfs_io_unit io;
nfs41_write_verf verf;
pnfs_io_thread *thread = (pnfs_io_thread*)args;
pnfs_io_pattern *pattern = thread->pattern;
stateid4 *state = pattern->stateid;
pnfs_data_server *server;
pnfs_file_layout *layout = pattern->layout;
nfs41_client *client;
nfs41_path_fh *commit_file;
const uint64_t offset_start = thread->offset;
uint64_t commit_len;
uint32_t maxwritesize, bytes_written, total_written;
enum pnfs_status status;
enum nfsstat4 nfsstat;
dprintf(IOLVL, "--> file_layout_write_thread(%u)\n", thread->id);
/* get the data server for this thread */
status = thread_data_server(thread, &server);
if (status) {
eprintf("thread_data_server() failed with %s\n",
pnfs_error_string(status));
goto out;
}
/* find or establish a client for this data server */
status = pnfs_data_server_client(pattern->root,
server, pattern->default_lease, &client);
if (status) {
eprintf("pnfs_data_server_client() failed with %s\n",
pnfs_error_string(status));
goto out;
}
retry_write:
thread->offset = offset_start;
thread->stable = DATA_SYNC4;
commit_file = NULL;
total_written = 0;
while ((status = thread_next_unit(thread, &io)) == PNFS_PENDING) {
maxwritesize = max_write_size(client->session, &io.file->fh);
if (io.length > maxwritesize)
io.length = maxwritesize;
nfsstat = nfs41_write(client->session, io.file, state, io.buffer,
(uint32_t)io.length, io.offset, UNSTABLE4, &bytes_written, &verf);
if (nfsstat) {
eprintf("nfs41_write() failed with %s\n",
nfs_error_string(nfsstat));
status = map_ds_error(nfsstat, &layout->layout);
break;
}
if (!verify_write(&verf, &thread->stable))
goto retry_write;
total_written += bytes_written;
thread->offset += bytes_written;
commit_file = io.file;
}
commit_len = thread->offset - pattern->offset_start;
/* nothing to commit */
if (commit_len == 0)
goto out;
/* layout changed; redo all io against metadata server */
if (status == PNFSERR_LAYOUT_CHANGED)
goto out;
/* XXX: commit offsets (and possibly fh) are different in dense layouts! */
if (is_dense(layout))
goto out;
/* the data is already in stable storage */
if (thread->stable != UNSTABLE4)
goto out;
/* the metadata server expects us to commit there instead */
if (should_commit_to_mds(layout))
goto out;
dprintf(1, "sending COMMIT to data server for offset=%d and len=%d\n",
pattern->offset_start, commit_len);
nfsstat = nfs41_commit(client->session, commit_file,
pattern->offset_start, (uint32_t)commit_len, 0);
/* on successful commit, leave pnfs_status unchanged; if the layout
* was recalled, we still want to return the error */
if (nfsstat == NFS4_OK)
thread->stable = DATA_SYNC4;
else
status = map_ds_error(nfsstat, &pattern->layout->layout);
out:
dprintf(IOLVL, "<-- file_layout_write_thread(%u) returning %s\n",
thread->id, pnfs_error_string(status));
return status;
}
enum pnfs_status pnfs_read(
IN nfs41_root *root,
IN nfs41_session *session,
IN nfs41_path_fh *file,
IN stateid4 *stateid,
IN pnfs_file_layout *layout,
IN uint64_t offset,
IN uint64_t length,
OUT unsigned char *buffer_out,
OUT ULONG *len_out)
{
pnfs_io_pattern pattern;
enum pnfs_status status;
dprintf(IOLVL, "--> pnfs_read(%llu, %llu)\n", offset, length);
*len_out = 0;
status = pattern_init(&pattern, root, file, stateid,
layout, buffer_out, offset, length, session->lease_time);
if (status) {
eprintf("pattern_init() failed with %s\n",
pnfs_error_string(status));
goto out;
}
status = pattern_fork(&pattern, file_layout_read_thread);
if (status != PNFS_SUCCESS && status != PNFS_READ_EOF)
goto out_free_pattern;
*len_out = (ULONG)pattern_bytes_transferred(&pattern, NULL);
out_free_pattern:
pattern_free(&pattern);
out:
dprintf(IOLVL, "<-- pnfs_read() returning %s\n",
pnfs_error_string(status));
return status;
}
enum pnfs_status pnfs_write(
IN nfs41_root *root,
IN nfs41_session *session,
IN nfs41_path_fh *file,
IN stateid4 *stateid,
IN pnfs_file_layout *layout,
IN uint64_t offset,
IN uint64_t length,
IN unsigned char *buffer,
OUT ULONG *len_out)
{
pnfs_io_pattern pattern;
uint64_t new_last_offset;
enum stable_how4 stable;
enum pnfs_status status;
enum nfsstat4 nfsstat;
dprintf(IOLVL, "--> pnfs_write(%llu, %llu)\n", offset, length);
*len_out = 0;
status = pattern_init(&pattern, root, file, stateid,
layout, buffer, offset, length, session->lease_time);
if (status) {
eprintf("pattern_init() failed with %s\n",
pnfs_error_string(status));
goto out;
}
status = pattern_fork(&pattern, file_layout_write_thread);
/* on layout recall, we still attempt to commit what we wrote */
if (status != PNFS_SUCCESS && status != PNFSERR_LAYOUT_RECALLED)
goto out_free_pattern;
*len_out = (ULONG)pattern_bytes_transferred(&pattern, &stable);
if (*len_out == 0)
goto out_free_pattern;
if (stable == UNSTABLE4) {
/* not all data was committed, so commit to metadata server.
* pass do_getattr=0 to nfs41_commit() because we'll GETATTR
* after LAYOUTCOMMIT */
dprintf(1, "sending COMMIT to meta server for offset=%d and len=%d\n",
offset, *len_out);
nfsstat = nfs41_commit(session, pattern.meta_file, offset, *len_out, 0);
if (nfsstat) {
dprintf(IOLVL, "nfs41_commit() failed with %s\n",
nfs_error_string(nfsstat));
status = PNFSERR_IO;
goto out_free_pattern;
}
}
/* send LAYOUTCOMMIT */
new_last_offset = offset + *len_out - 1;
nfsstat = pnfs_rpc_layoutcommit(session, pattern.meta_file,
&pattern.layout->layout.state, offset, *len_out,
&new_last_offset, NULL);
if (nfsstat) {
dprintf(IOLVL, "pnfs_rpc_layoutcommit() failed with %s\n",
nfs_error_string(nfsstat));
/* acceptable failure? if COMMIT worked, return success */
}
out_free_pattern:
pattern_free(&pattern);
out:
dprintf(IOLVL, "<-- pnfs_write() returning %s\n",
pnfs_error_string(status));
return status;
}

835
daemon/pnfs_layout.c Normal file
View file

@ -0,0 +1,835 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <stdio.h>
#include "nfs41_ops.h"
#include "nfs41_callback.h"
#include "util.h"
#include "daemon_debug.h"
#define FLLVL 2 /* dprintf level for file layout logging */
/* pnfs_file_layout_list */
struct pnfs_file_layout_list {
struct list_entry head;
CRITICAL_SECTION lock;
};
#define layout_entry(pos) list_container(pos, pnfs_file_layout, entry)
static enum pnfs_status layout_create(
IN const nfs41_fh *meta_fh,
OUT pnfs_file_layout **layout_out)
{
pnfs_file_layout *layout;
enum pnfs_status status = PNFS_SUCCESS;
layout = calloc(1, sizeof(pnfs_file_layout));
if (layout == NULL) {
status = PNFSERR_RESOURCES;
goto out;
}
layout->layout.type = PNFS_LAYOUTTYPE_FILE;
fh_copy(&layout->meta_fh, meta_fh);
InitializeSRWLock(&layout->layout.lock);
*layout_out = layout;
out:
return status;
}
static void layout_free(
IN pnfs_file_layout *layout)
{
free(layout->filehandles.arr);
free(layout);
}
static int layout_entry_compare(
IN const struct list_entry *entry,
IN const void *value)
{
const pnfs_file_layout *layout = layout_entry(entry);
const nfs41_fh *meta_fh = (const nfs41_fh*)value;
const nfs41_fh *layout_fh = (const nfs41_fh*)&layout->meta_fh;
const uint32_t diff = layout_fh->len - meta_fh->len;
return diff ? diff : memcmp(layout_fh->fh, meta_fh->fh, meta_fh->len);
}
static enum pnfs_status layout_entry_find(
IN struct pnfs_file_layout_list *layouts,
IN const nfs41_fh *meta_fh,
OUT struct list_entry **entry_out)
{
*entry_out = list_search(&layouts->head, meta_fh, layout_entry_compare);
return *entry_out ? PNFS_SUCCESS : PNFSERR_NO_LAYOUT;
}
enum pnfs_status pnfs_file_layout_list_create(
OUT struct pnfs_file_layout_list **layouts_out)
{
struct pnfs_file_layout_list *layouts;
enum pnfs_status status = PNFS_SUCCESS;
layouts = calloc(1, sizeof(struct pnfs_file_layout_list));
if (layouts == NULL) {
status = PNFSERR_RESOURCES;
goto out;
}
list_init(&layouts->head);
InitializeCriticalSection(&layouts->lock);
*layouts_out = layouts;
out:
return status;
}
void pnfs_file_layout_list_free(
IN struct pnfs_file_layout_list *layouts)
{
struct list_entry *entry, *tmp;
EnterCriticalSection(&layouts->lock);
list_for_each_tmp(entry, tmp, &layouts->head)
layout_free(layout_entry(entry));
LeaveCriticalSection(&layouts->lock);
free(layouts);
}
static enum pnfs_status file_layout_find_or_create(
IN struct pnfs_file_layout_list *layouts,
IN const nfs41_fh *meta_fh,
OUT pnfs_file_layout **layout_out)
{
struct list_entry *entry;
enum pnfs_status status;
dprintf(FLLVL, "--> file_layout_find_or_create()\n");
EnterCriticalSection(&layouts->lock);
/* search for an existing layout */
status = layout_entry_find(layouts, meta_fh, &entry);
if (status) {
/* create a new layout */
pnfs_file_layout *layout;
status = layout_create(meta_fh, &layout);
if (status == PNFS_SUCCESS) {
/* add it to the list */
list_add_head(&layouts->head, &layout->entry);
*layout_out = layout;
dprintf(FLLVL, "<-- file_layout_find_or_create() "
"returning new layout %p\n", layout);
} else {
dprintf(FLLVL, "<-- file_layout_find_or_create() "
"returning %s\n", pnfs_error_string(status));
}
} else {
*layout_out = layout_entry(entry);
dprintf(FLLVL, "<-- file_layout_find_or_create() "
"returning existing layout %p\n", *layout_out);
}
LeaveCriticalSection(&layouts->lock);
return status;
}
static enum pnfs_status file_layout_find_and_delete(
IN struct pnfs_file_layout_list *layouts,
IN const nfs41_fh *meta_fh)
{
struct list_entry *entry;
enum pnfs_status status;
dprintf(FLLVL, "--> file_layout_find_and_delete()\n");
EnterCriticalSection(&layouts->lock);
status = layout_entry_find(layouts, meta_fh, &entry);
if (status == PNFS_SUCCESS) {
list_remove(entry);
layout_free(layout_entry(entry));
}
LeaveCriticalSection(&layouts->lock);
dprintf(FLLVL, "<-- file_layout_find_and_delete() "
"returning %s\n", pnfs_error_string(status));
return status;
}
/* pnfs_file_layout */
static enum pnfs_status file_layout_fetch(
IN OUT pnfs_file_layout *layout,
IN nfs41_session *session,
IN nfs41_path_fh *meta_file,
IN stateid4 *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length)
{
enum pnfs_status pnfsstat = PNFS_SUCCESS;
enum nfsstat4 nfsstat;
dprintf(FLLVL, "--> file_layout_fetch(%s, seqid=%u)\n",
pnfs_iomode_string(iomode), layout->layout.state.seqid);
nfsstat = pnfs_rpc_layoutget(session, meta_file,
state, iomode, offset, length, layout);
if (nfsstat) {
dprintf(FLLVL, "pnfs_rpc_layoutget() failed with %s\n",
nfs_error_string(nfsstat));
pnfsstat = PNFSERR_NOT_SUPPORTED;
}
switch (nfsstat) {
case NFS4_OK:
/* mark granted and clear other flags */
layout->layout.status = PNFS_LAYOUT_GRANTED;
dprintf(FLLVL, "Received layout:\n");
dprint_layout(FLLVL, layout);
break;
case NFS4ERR_BADIOMODE:
/* don't try RW again */
if (iomode == PNFS_IOMODE_RW)
layout->layout.status |= PNFS_LAYOUT_NOT_RW;
break;
case NFS4ERR_LAYOUTUNAVAILABLE:
case NFS4ERR_UNKNOWN_LAYOUTTYPE:
case NFS4ERR_BADLAYOUT:
/* don't try again at all */
layout->layout.status |= PNFS_LAYOUT_UNAVAILABLE;
break;
}
dprintf(FLLVL, "<-- file_layout_fetch() returning %s\n",
pnfs_error_string(pnfsstat));
return pnfsstat;
}
static bool_t layout_recalled(
IN const pnfs_layout *layout)
{
return (layout->status & PNFS_LAYOUT_RECALLED) != 0;
}
static bool_t layout_granted(
IN const pnfs_layout *layout)
{
return (layout->status & PNFS_LAYOUT_GRANTED) != 0;
}
static bool_t layout_not_rw(
IN const pnfs_layout *layout)
{
return (layout->status & PNFS_LAYOUT_NOT_RW) != 0;
}
static bool_t will_never_grant(
IN const pnfs_layout *layout,
IN enum pnfs_iomode iomode)
{
return (layout->status & PNFS_LAYOUT_UNAVAILABLE) != 0
|| (iomode == PNFS_IOMODE_RW && layout_not_rw(layout));
}
static enum pnfs_status layout_grant_status(
IN const pnfs_layout *layout,
IN enum pnfs_iomode iomode)
{
enum pnfs_status status = PNFS_PENDING;
if (layout_recalled(layout)) {
/* don't use a recalled layout */
status = PNFSERR_LAYOUT_RECALLED;
} else if (layout_granted(layout)) {
/* the layout is granted; use it if it's compatible */
status = PNFS_SUCCESS;
} else if (will_never_grant(layout, iomode)) {
/* an error from LAYOUTGET indicated that the server
* won't ever grant this layout, so stop trying */
status = PNFSERR_NOT_SUPPORTED;
}
return status;
}
static enum pnfs_status file_layout_cache(
IN OUT pnfs_file_layout *layout,
IN nfs41_session *session,
IN nfs41_path_fh *meta_file,
IN stateid4 *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length)
{
enum pnfs_status status;
/* use a shared lock to see if it's already been granted */
AcquireSRWLockShared(&layout->layout.lock);
status = layout_grant_status(&layout->layout, iomode);
ReleaseSRWLockShared(&layout->layout.lock);
if (status == PNFS_PENDING) {
/* use an exclusive lock while attempting to get a new layout */
AcquireSRWLockExclusive(&layout->layout.lock);
status = layout_grant_status(&layout->layout, iomode);
if (status == PNFS_PENDING) {
/* if there's an existing layout stateid, use it */
if (layout->layout.state.seqid)
state = &layout->layout.state;
if (!layout_not_rw(&layout->layout)) {
/* try to get a RW layout first */
status = file_layout_fetch(layout, session,
meta_file, state, PNFS_IOMODE_RW, offset, length);
}
if (status && iomode == PNFS_IOMODE_READ) {
/* fall back on READ if necessary */
status = file_layout_fetch(layout, session,
meta_file, state, iomode, offset, length);
}
}
ReleaseSRWLockExclusive(&layout->layout.lock);
}
return status;
}
static enum pnfs_status layout_compatible(
IN OUT pnfs_layout *layout,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length)
{
enum pnfs_status status = PNFS_SUCCESS;
AcquireSRWLockShared(&layout->lock);
if (iomode == PNFS_IOMODE_RW && layout->iomode == PNFS_IOMODE_READ) {
status = PNFSERR_NOT_SUPPORTED;
goto out_unlock;
}
if (offset < layout->offset ||
offset + length > layout->offset + layout->length) {
status = PNFSERR_NOT_SUPPORTED;
goto out_unlock;
}
out_unlock:
ReleaseSRWLockShared(&layout->lock);
return status;
}
static enum pnfs_status file_device_status(
IN const pnfs_layout *layout)
{
enum pnfs_status status = PNFS_PENDING;
if (layout_recalled(layout)) {
/* don't fetch deviceinfo for a recalled layout */
status = PNFSERR_LAYOUT_RECALLED;
} else if (layout->status & PNFS_LAYOUT_HAS_DEVICE) {
/* deviceinfo already cached */
status = PNFS_SUCCESS;
}
return status;
}
static enum pnfs_status file_layout_device(
IN OUT pnfs_file_layout *layout,
IN nfs41_session *session)
{
enum pnfs_status status = PNFS_PENDING;
/* use a shared lock to see if we already have a device */
AcquireSRWLockShared(&layout->layout.lock);
status = file_device_status(&layout->layout);
ReleaseSRWLockShared(&layout->layout.lock);
if (status == PNFS_PENDING) {
/* use an exclusive lock to look up device info */
AcquireSRWLockExclusive(&layout->layout.lock);
status = file_device_status(&layout->layout);
if (status == PNFS_PENDING) {
status = pnfs_file_device_get(session, session->client->devices,
layout->deviceid, &layout->device);
if (status == PNFS_SUCCESS)
layout->layout.status |= PNFS_LAYOUT_HAS_DEVICE;
}
ReleaseSRWLockExclusive(&layout->layout.lock);
}
return status;
}
static enum pnfs_status file_layout_get(
IN OUT pnfs_file_layout *layout,
IN nfs41_session *session,
IN nfs41_path_fh *meta_file,
IN stateid4 *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length)
{
enum pnfs_status status;
/* request a range for the entire file */
status = file_layout_cache(layout, session,
meta_file, state, iomode, 0, NFS4_UINT64_MAX);
if (status) {
dprintf(FLLVL, "file_layout_cache() failed with %s\n",
pnfs_error_string(status));
goto out;
}
/* fail if we don't get everything we asked for */
status = layout_compatible(&layout->layout, iomode, offset, length);
if (status) {
dprintf(FLLVL, "file_layout_compatible() failed with %s\n",
pnfs_error_string(status));
goto out;
}
/* make sure we have a device for the layout */
status = file_layout_device(layout, session);
if (status) {
dprintf(FLLVL, "file_layout_device() failed with %s\n",
pnfs_error_string(status));
goto out;
}
out:
return status;
}
static enum pnfs_status layout_return_status(
IN const pnfs_file_layout *layout)
{
return (layout->layout.status & PNFS_LAYOUT_GRANTED) == 0
? PNFS_SUCCESS : PNFS_PENDING;
}
static enum pnfs_status file_layout_return(
IN nfs41_session *session,
IN nfs41_path_fh *file,
IN pnfs_file_layout *layout)
{
enum pnfs_status status;
enum nfsstat4 nfsstat;
dprintf(FLLVL, "--> file_layout_return()\n");
/* under shared lock, determine whether we need to return the layout */
AcquireSRWLockShared(&layout->layout.lock);
status = layout_return_status(layout);
ReleaseSRWLockShared(&layout->layout.lock);
if (status == PNFS_PENDING) {
/* under exclusive lock, return the layout and reset status flags */
AcquireSRWLockExclusive(&layout->layout.lock);
status = layout_return_status(layout);
if (status == PNFS_PENDING) {
/* reset the granted flag */
layout->layout.status &= ~PNFS_LAYOUT_GRANTED;
nfsstat = pnfs_rpc_layoutreturn(session, file, layout);
if (nfsstat) {
eprintf("pnfs_rpc_layoutreturn() failed with %s\n",
nfs_error_string(nfsstat));
status = PNFSERR_NO_LAYOUT;
} else {
status = PNFS_SUCCESS;
}
}
ReleaseSRWLockExclusive(&layout->layout.lock);
}
dprintf(FLLVL, "<-- file_layout_return() returning %s\n",
pnfs_error_string(status));
return status;
}
/* nfs41_open_state */
static enum pnfs_status client_supports_pnfs(
IN nfs41_client *client)
{
enum pnfs_status status;
AcquireSRWLockShared(&client->exid_lock);
status = client->roles & EXCHGID4_FLAG_USE_PNFS_MDS
? PNFS_SUCCESS : PNFSERR_NOT_SUPPORTED;
ReleaseSRWLockShared(&client->exid_lock);
return status;
}
static enum pnfs_status fs_supports_layout(
IN const nfs41_superblock *superblock,
IN enum pnfs_layout_type type)
{
const uint32_t flag = 1 << (type - 1);
return (superblock->layout_types & flag) == 0
? PNFSERR_NOT_SUPPORTED : PNFS_SUCCESS;
}
static enum pnfs_status open_state_layout_cached(
IN nfs41_open_state *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length,
OUT pnfs_file_layout **layout_out)
{
enum pnfs_status status = PNFSERR_NO_LAYOUT;
if (state->layout) {
status = PNFS_SUCCESS;
*layout_out = state->layout;
dprintf(FLLVL, "pnfs_open_state_layout() found "
"cached layout %p\n", *layout_out);
}
return status;
}
enum pnfs_status pnfs_open_state_layout(
IN struct pnfs_file_layout_list *layouts,
IN nfs41_session *session,
IN nfs41_open_state *state,
IN enum pnfs_iomode iomode,
IN uint64_t offset,
IN uint64_t length,
OUT pnfs_file_layout **layout_out)
{
pnfs_file_layout *layout;
enum pnfs_status status;
dprintf(FLLVL, "--> pnfs_open_state_layout()\n");
status = client_supports_pnfs(session->client);
if (status)
goto out;
status = fs_supports_layout(state->file.fh.superblock, PNFS_LAYOUTTYPE_FILE);
if (status)
goto out;
/* under shared lock, check open state for cached layouts */
AcquireSRWLockShared(&state->lock);
status = open_state_layout_cached(state, iomode, offset, length, &layout);
ReleaseSRWLockShared(&state->lock);
if (status) {
/* under exclusive lock, find or create a layout for this file */
AcquireSRWLockExclusive(&state->lock);
status = open_state_layout_cached(state, iomode, offset, length, &layout);
if (status) {
status = file_layout_find_or_create(layouts, &state->file.fh, &layout);
if (status == PNFS_SUCCESS) {
state->layout = layout;
dprintf(FLLVL, "pnfs_open_state_layout() caching layout %p\n",
state->layout);
}
}
ReleaseSRWLockExclusive(&state->lock);
if (status)
goto out;
}
/* make sure the layout can satisfy this request */
status = file_layout_get(layout, session, &state->file,
&state->stateid, iomode, offset, length);
if (status) {
dprintf(FLLVL, "file_layout_get() failed with %s\n",
pnfs_error_string(status));
goto out;
}
*layout_out = layout;
out:
dprintf(FLLVL, "<-- pnfs_open_state_layout() returning %s\n",
pnfs_error_string(status));
return status;
}
void pnfs_open_state_close(
IN nfs41_session *session,
IN nfs41_open_state *state,
IN bool_t remove)
{
pnfs_file_layout *layout;
bool_t return_on_close;
enum pnfs_status status;
AcquireSRWLockExclusive(&state->lock);
layout = state->layout;
state->layout = NULL;
ReleaseSRWLockExclusive(&state->lock);
if (layout) {
/* check if we need to return the layout on close */
AcquireSRWLockShared(&layout->layout.lock);
return_on_close = layout->layout.return_on_close;
ReleaseSRWLockShared(&layout->layout.lock);
if (return_on_close) {
status = file_layout_return(session, &state->file, layout);
if (status)
eprintf("file_layout_return() failed with %s\n",
pnfs_error_string(status));
}
}
if (remove && session->client->layouts) {
/* free the layout when the file is removed */
file_layout_find_and_delete(session->client->layouts, &state->file.fh);
}
}
/* pnfs_layout_recall */
/* expects the caller to have an exclusive lock */
static enum pnfs_status layout_recall_return(
IN pnfs_layout *layout)
{
dprintf(FLLVL, "layout_recall_return() 'forgetting' layout\n");
/* since we're forgetful, we don't actually return the layout;
* just zero the stateid since it won't be valid anymore */
ZeroMemory(&layout->state, sizeof(layout->state));
layout->status = 0;
return PNFS_SUCCESS;
}
static enum pnfs_status file_layout_recall(
IN pnfs_file_layout *layout,
IN const struct cb_layoutrecall_args *recall)
{
enum pnfs_status status = PNFS_SUCCESS;
/* under an exclusive lock, flag the layout as recalled */
AcquireSRWLockExclusive(&layout->layout.lock);
if (layout->layout.io_count == 0) {
/* if there is no pending io, return the layout now */
status = layout_recall_return(&layout->layout);
} else {
/* flag the layout as recalled so it can be returned after io */
layout->layout.status |= PNFS_LAYOUT_RECALLED;
if (recall->changed)
layout->layout.status |= PNFS_LAYOUT_CHANGED;
}
/* if we got a stateid, update the layout's seqid */
if (recall->recall.type == PNFS_RETURN_FILE)
layout->layout.state.seqid = recall->recall.args.file.stateid.seqid;
ReleaseSRWLockExclusive(&layout->layout.lock);
return status;
}
static enum pnfs_status file_layout_recall_file(
IN struct pnfs_file_layout_list *layouts,
IN const struct cb_layoutrecall_args *recall)
{
struct list_entry *entry;
enum pnfs_status status;
dprintf(FLLVL, "--> file_layout_recall_file()\n");
EnterCriticalSection(&layouts->lock);
status = layout_entry_find(layouts, &recall->recall.args.file.fh, &entry);
if (status == PNFS_SUCCESS)
status = file_layout_recall(layout_entry(entry), recall);
LeaveCriticalSection(&layouts->lock);
dprintf(FLLVL, "<-- file_layout_recall_file() returning %s\n",
pnfs_error_string(status));
return status;
}
static bool_t fsid_matches(
IN const nfs41_fsid *lhs,
IN const nfs41_fsid *rhs)
{
return lhs->major == rhs->major
&& lhs->minor == rhs->minor;
}
static enum pnfs_status file_layout_recall_fsid(
IN struct pnfs_file_layout_list *layouts,
IN const struct cb_layoutrecall_args *recall)
{
struct list_entry *entry;
pnfs_file_layout *layout;
nfs41_fh *fh;
enum pnfs_status status = PNFSERR_NO_LAYOUT;
dprintf(FLLVL, "--> file_layout_recall_fsid(%llu, %llu)\n",
recall->recall.args.fsid.major, recall->recall.args.fsid.minor);
EnterCriticalSection(&layouts->lock);
list_for_each(entry, &layouts->head) {
layout = layout_entry(entry);
/* no locks needed to read layout.meta_fh or superblock.fsid,
* because they are only written once on creation */
fh = &layout->meta_fh;
if (fsid_matches(&recall->recall.args.fsid, &fh->superblock->fsid))
status = file_layout_recall(layout, recall);
}
LeaveCriticalSection(&layouts->lock);
dprintf(FLLVL, "<-- file_layout_recall_fsid() returning %s\n",
pnfs_error_string(status));
return status;
}
static enum pnfs_status file_layout_recall_all(
IN struct pnfs_file_layout_list *layouts,
IN const struct cb_layoutrecall_args *recall)
{
struct list_entry *entry;
enum pnfs_status status = PNFSERR_NO_LAYOUT;
dprintf(FLLVL, "--> file_layout_recall_all()\n");
EnterCriticalSection(&layouts->lock);
list_for_each(entry, &layouts->head)
status = file_layout_recall(layout_entry(entry), recall);
LeaveCriticalSection(&layouts->lock);
dprintf(FLLVL, "<-- file_layout_recall_all() returning %s\n",
pnfs_error_string(status));
return status;
}
enum pnfs_status pnfs_file_layout_recall(
IN struct pnfs_file_layout_list *layouts,
IN const struct cb_layoutrecall_args *recall)
{
enum pnfs_status status = PNFS_SUCCESS;
dprintf(FLLVL, "--> pnfs_file_layout_recall(%u, %s, %u)\n",
recall->recall.type, pnfs_iomode_string(recall->iomode),
recall->changed);
if (recall->type != PNFS_LAYOUTTYPE_FILE) {
dprintf(FLLVL, "invalid layout type %u (%s)!\n",
recall->type, pnfs_layout_type_string(recall->type));
status = PNFSERR_NOT_SUPPORTED;
goto out;
}
switch (recall->recall.type) {
case PNFS_RETURN_FILE:
status = file_layout_recall_file(layouts, recall);
break;
case PNFS_RETURN_FSID:
status = file_layout_recall_fsid(layouts, recall);
break;
case PNFS_RETURN_ALL:
status = file_layout_recall_all(layouts, recall);
break;
default:
dprintf(FLLVL, "invalid return type %u!\n", recall->recall);
status = PNFSERR_NOT_SUPPORTED;
goto out;
}
/* XXX: bulk layout recalls require invalidation of cached device info!
* see CB_LAYOUTRECALL: http://tools.ietf.org/html/rfc5661#section-20.3.3 */
out:
dprintf(FLLVL, "<-- pnfs_file_layout_recall() returning %s\n",
pnfs_error_string(status));
return status;
}
enum pnfs_status pnfs_layout_io_start(
IN pnfs_layout *layout)
{
enum pnfs_status status = PNFS_SUCCESS;
AcquireSRWLockExclusive(&layout->lock);
if (layout_recalled(layout)) {
/* don't start any more io if the layout has been recalled */
status = PNFSERR_LAYOUT_RECALLED;
dprintf(FLLVL, "pnfs_layout_io_start() failed, layout was recalled\n");
} else {
/* take a reference on the layout, so that it won't be recalled
* until all io is finished */
layout->io_count++;
dprintf(FLLVL, "pnfs_layout_io_start(): count -> %u\n",
layout->io_count);
}
ReleaseSRWLockExclusive(&layout->lock);
return status;
}
void pnfs_layout_io_finished(
IN pnfs_layout *layout)
{
AcquireSRWLockExclusive(&layout->lock);
/* return the reference to signify that an io request is finished */
layout->io_count--;
dprintf(FLLVL, "pnfs_layout_io_finished() count -> %u\n",
layout->io_count);
if (layout->io_count > 0) /* more io pending */
goto out_unlock;
/* once all io is finished, check for layout recalls */
if (layout->status & PNFS_LAYOUT_RECALLED)
layout_recall_return(layout);
out_unlock:
ReleaseSRWLockExclusive(&layout->lock);
}

385
daemon/rbtree.c Normal file
View file

@ -0,0 +1,385 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/lib/rbtree.c
*/
#include "rbtree.h"
#pragma warning(disable:4706)
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
/*
* This function returns the first node (in sort order) of the tree.
*/
struct rb_node *rb_first(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_left)
n = n->rb_left;
return n;
}
struct rb_node *rb_last(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_right)
n = n->rb_right;
return n;
}
struct rb_node *rb_next(const struct rb_node *node)
{
struct rb_node *parent;
if (rb_parent(node) == node)
return NULL;
/* If we have a right-hand child, go down and then left as far
as we can. */
if (node->rb_right) {
node = node->rb_right;
while (node->rb_left)
node=node->rb_left;
return (struct rb_node *)node;
}
/* No right-hand children. Everything down and left is
smaller than us, so any 'next' node must be in the general
direction of our parent. Go up the tree; any time the
ancestor is a right-hand child of its parent, keep going
up. First time it's a left-hand child of its parent, said
parent is our 'next' node. */
while ((parent = rb_parent(node)) && node == parent->rb_right)
node = parent;
return parent;
}
struct rb_node *rb_prev(const struct rb_node *node)
{
struct rb_node *parent;
if (rb_parent(node) == node)
return NULL;
/* If we have a left-hand child, go down and then right as far
as we can. */
if (node->rb_left) {
node = node->rb_left;
while (node->rb_right)
node=node->rb_right;
return (struct rb_node *)node;
}
/* No left-hand children. Go up till we find an ancestor which
is a right-hand child of its parent */
while ((parent = rb_parent(node)) && node == parent->rb_left)
node = parent;
return parent;
}
void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root)
{
struct rb_node *parent = rb_parent(victim);
/* Set the surrounding nodes to point to the replacement */
if (parent) {
if (victim == parent->rb_left)
parent->rb_left = new;
else
parent->rb_right = new;
} else {
root->rb_node = new;
}
if (victim->rb_left)
rb_set_parent(victim->rb_left, new);
if (victim->rb_right)
rb_set_parent(victim->rb_right, new);
/* Copy the pointers/colour from the victim to the replacement */
*new = *victim;
}

159
daemon/rbtree.h Normal file
View file

@ -0,0 +1,159 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/include/linux/rbtree.h
To use rbtrees you'll have to implement your own insert and search cores.
This will avoid us to use callbacks and to drop drammatically performances.
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
Some example of insert and search follows here. The search is a plain
normal search over an ordered tree. The insert instead must be implemented
int two steps: as first thing the code must insert the element in
order as a red leaf in the tree, then the support library function
rb_insert_color() must be called. Such function will do the
not trivial work to rebalance the rbtree if necessary.
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
rb_link_node(node, parent, p);
return NULL;
}
static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
out:
return ret;
}
-----------------------------------------------------------------------
*/
#ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H
#include <stddef.h>
struct rb_node
{
size_t rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
};
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static __inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (size_t)p;
}
static __inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
#define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) CONTAINING_RECORD(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(const struct rb_node *);
extern struct rb_node *rb_prev(const struct rb_node *);
extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static __inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (size_t)parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
#endif /* _LINUX_RBTREE_H */

627
daemon/readdir.c Normal file
View file

@ -0,0 +1,627 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include <stdlib.h>
#include "from_kernel.h"
#include "nfs41_ops.h"
#include "daemon_debug.h"
#include "upcall.h"
#include "util.h"
typedef union _FILE_DIR_INFO_UNION {
ULONG NextEntryOffset;
FILE_NAMES_INFORMATION fni;
FILE_DIRECTORY_INFO fdi;
FILE_FULL_DIR_INFO ffdi;
FILE_ID_FULL_DIR_INFO fifdi;
FILE_BOTH_DIR_INFORMATION fbdi;
FILE_ID_BOTH_DIR_INFO fibdi;
} FILE_DIR_INFO_UNION, *PFILE_DIR_INFO_UNION;
/* NFS41_DIR_QUERY */
int parse_readdir(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
readdir_upcall_args *args = &upcall->args.readdir;
status = safe_read(&buffer, &length, &args->query_class, sizeof(args->query_class));
if (status) goto out;
status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
if (status) goto out;
status = get_name(&buffer, &length, args->filter);
if (status) goto out;
status = safe_read(&buffer, &length, &args->initial, sizeof(args->initial));
if (status) goto out;
status = safe_read(&buffer, &length, &args->restart, sizeof(args->restart));
if (status) goto out;
status = safe_read(&buffer, &length, &args->single, sizeof(args->single));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(args->root));
if (status) goto out;
status = safe_read(&buffer, &length, &args->state, sizeof(args->state));
if (status) goto out;
status = safe_read(&buffer, &length, &args->cookie, sizeof(args->cookie));
if (status) goto out;
if (args->cookie == INVALID_HANDLE_VALUE) {
dprintf(1, "upcall passing empty cookie\n");
args->cookie = NULL;
}
out:
if (status)
eprintf("parsing NFS41_DIR_QUERY failed with %d\n", status);
else
dprintf(1, "parsing NFS41_DIR_QUERY: info_class=%d buf_len=%d "
"filter='%s'\n\tInitial\\Restart\\Single %d\\%d\\%d "
"root=0x%p state=0x%p cookie=0x%p\n",
args->query_class, args->buf_len, args->filter,
args->initial, args->restart, args->single,
args->root, args->state, args->cookie);
return status;
}
#define FILTER_STAR '*'
#define FILTER_QM '>'
static __inline int readdir_has_wildcards(
const char *filter)
{
return strchr(filter, FILTER_STAR) || strchr(filter, FILTER_QM);
}
static __inline const char* skip_stars(
const char *filter)
{
while (*filter == FILTER_STAR)
filter++;
return filter;
}
static int readdir_filter(
const char *filter,
const char *name)
{
const char *f = filter, *n = name;
while (*f && *n) {
if (*f == FILTER_STAR) {
f = skip_stars(f);
if (*f == '\0')
return 1;
while (*n && !readdir_filter(f, n))
n++;
} else if (*f == FILTER_QM || *f == *n) {
f++;
n++;
} else
return 0;
}
return *f == *n || *skip_stars(f) == '\0';
}
static uint32_t readdir_size_for_entry(
IN int query_class,
IN uint32_t wname_size)
{
uint32_t needed = wname_size;
switch (query_class)
{
case FileDirectoryInformation:
needed += FIELD_OFFSET(FILE_DIRECTORY_INFO, FileName);
break;
case FileIdFullDirectoryInformation:
needed += FIELD_OFFSET(FILE_ID_FULL_DIR_INFO, FileName);
break;
case FileFullDirectoryInformation:
needed += FIELD_OFFSET(FILE_FULL_DIR_INFO, FileName);
break;
case FileIdBothDirectoryInformation:
needed += FIELD_OFFSET(FILE_ID_BOTH_DIR_INFO, FileName);
break;
case FileBothDirectoryInformation:
needed += FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName);
break;
case FileNamesInformation:
needed += FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName);
break;
default:
eprintf("unhandled dir query class %d\n", query_class);
return 0;
}
return needed;
}
static void readdir_copy_dir_info(
IN nfs41_readdir_entry *entry,
IN PFILE_DIR_INFO_UNION info)
{
info->fdi.FileIndex = 0;
nfs_time_to_file_time(&entry->attr_info.time_create,
&info->fdi.CreationTime);
nfs_time_to_file_time(&entry->attr_info.time_access,
&info->fdi.LastAccessTime);
nfs_time_to_file_time(&entry->attr_info.time_modify,
&info->fdi.LastWriteTime);
/* XXX: was using 'change' attr, but that wasn't giving a time */
nfs_time_to_file_time(&entry->attr_info.time_modify,
&info->fdi.ChangeTime);
info->fdi.EndOfFile.QuadPart =
info->fdi.AllocationSize.QuadPart =
entry->attr_info.size;
info->fdi.FileAttributes = nfs_file_info_to_attributes(
&entry->attr_info);
}
static void readdir_copy_shortname(
IN LPCWSTR name,
OUT LPWSTR name_out,
OUT CCHAR *name_size_out)
{
/* GetShortPathName returns number of characters, not including \0 */
*name_size_out = (CCHAR)GetShortPathNameW(name, name_out, 12);
if (*name_size_out) {
*name_size_out++;
*name_size_out *= sizeof(WCHAR);
}
}
static void readdir_copy_full_dir_info(
IN nfs41_readdir_entry *entry,
IN PFILE_DIR_INFO_UNION info)
{
readdir_copy_dir_info(entry, info);
info->fifdi.EaSize = 0;
}
static void readdir_copy_both_dir_info(
IN nfs41_readdir_entry *entry,
IN LPWSTR wname,
IN PFILE_DIR_INFO_UNION info)
{
readdir_copy_full_dir_info(entry, info);
readdir_copy_shortname(wname, info->fbdi.ShortName,
&info->fbdi.ShortNameLength);
}
static void readdir_copy_filename(
IN LPCWSTR name,
IN uint32_t name_size,
OUT LPWSTR name_out,
OUT ULONG *name_size_out)
{
*name_size_out = name_size;
memcpy(name_out, name, name_size);
}
static int readdir_copy_entry(
IN readdir_upcall_args *args,
IN nfs41_readdir_entry *entry,
IN OUT unsigned char **dst_pos,
IN OUT uint32_t *dst_len)
{
int status = 0;
WCHAR wname[NFS4_OPAQUE_LIMIT];
uint32_t wname_len, wname_size, needed;
PFILE_DIR_INFO_UNION info;
wname_len = MultiByteToWideChar(CP_UTF8, 0,
entry->name, entry->name_len, wname, NFS4_OPAQUE_LIMIT);
wname_size = (wname_len - 1) * sizeof(WCHAR);
needed = readdir_size_for_entry(args->query_class, wname_size);
if (!needed || needed > *dst_len) {
status = -1;
goto out;
}
info = (PFILE_DIR_INFO_UNION)*dst_pos;
info->NextEntryOffset = align8(needed);
*dst_pos += info->NextEntryOffset;
*dst_len -= info->NextEntryOffset;
switch (args->query_class)
{
case FileNamesInformation:
info->fni.FileIndex = 0;
readdir_copy_filename(wname, wname_size,
info->fni.FileName, &info->fni.FileNameLength);
break;
case FileDirectoryInformation:
readdir_copy_dir_info(entry, info);
readdir_copy_filename(wname, wname_size,
info->fdi.FileName, &info->fdi.FileNameLength);
break;
case FileFullDirectoryInformation:
readdir_copy_full_dir_info(entry, info);
readdir_copy_filename(wname, wname_size,
info->ffdi.FileName, &info->ffdi.FileNameLength);
break;
case FileIdFullDirectoryInformation:
readdir_copy_full_dir_info(entry, info);
info->fibdi.FileId.QuadPart = (LONGLONG)entry->attr_info.fileid;
readdir_copy_filename(wname, wname_size,
info->fifdi.FileName, &info->fifdi.FileNameLength);
break;
case FileBothDirectoryInformation:
readdir_copy_both_dir_info(entry, wname, info);
readdir_copy_filename(wname, wname_size,
info->fbdi.FileName, &info->fbdi.FileNameLength);
break;
case FileIdBothDirectoryInformation:
readdir_copy_both_dir_info(entry, wname, info);
info->fibdi.FileId.QuadPart = (LONGLONG)entry->attr_info.fileid;
readdir_copy_filename(wname, wname_size,
info->fibdi.FileName, &info->fibdi.FileNameLength);
break;
default:
eprintf("unhandled dir query class %d\n", args->query_class);
status = -1;
break;
}
out:
return status;
}
#define COOKIE_DOT ((uint64_t)-2)
#define COOKIE_DOTDOT ((uint64_t)-1)
int readdir_add_dots(
IN readdir_upcall_args *args,
IN OUT unsigned char *entry_buf,
IN uint32_t entry_buf_len,
OUT uint32_t *len_out,
OUT uint32_t **last_offset)
{
int status = 0;
const uint32_t entry_len = (uint32_t)FIELD_OFFSET(nfs41_readdir_entry, name);
nfs41_readdir_entry *entry;
nfs41_open_state *state = args->state;
*len_out = 0;
*last_offset = NULL;
switch (args->cookie->cookie) {
case 0:
if (entry_buf_len < entry_len + 2) {
status = ERROR_BUFFER_OVERFLOW;
dprintf(1, "not enough room for '.' entry.\n");
goto out;
}
entry = (nfs41_readdir_entry*)entry_buf;
ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
status = nfs41_cached_getattr(state->session,
&state->file, &entry->attr_info);
if (status) {
dprintf(1, "failed to add '.' entry.\n");
goto out;
}
entry->cookie = COOKIE_DOT;
entry->name_len = 2;
StringCbCopyA(entry->name, entry->name_len, ".");
entry->next_entry_offset = entry_len + entry->name_len;
entry_buf += entry->next_entry_offset;
entry_buf_len -= entry->next_entry_offset;
*len_out += entry->next_entry_offset;
*last_offset = &entry->next_entry_offset;
if (args->single)
break;
/* else no break! */
case COOKIE_DOT:
if (entry_buf_len < entry_len + 3) {
status = ERROR_BUFFER_OVERFLOW;
dprintf(1, "not enough room for '..' entry.\n");
goto out;
}
/* XXX: this skips '..' when listing root fh */
if (state->file.name.len == 0)
break;
entry = (nfs41_readdir_entry*)entry_buf;
ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
status = nfs41_cached_getattr(state->session,
&state->parent, &entry->attr_info);
if (status) {
status = ERROR_FILE_NOT_FOUND;
dprintf(1, "failed to add '..' entry.\n");
goto out;
}
entry->cookie = COOKIE_DOTDOT;
entry->name_len = 3;
StringCbCopyA(entry->name, entry->name_len, "..");
entry->next_entry_offset = entry_len + entry->name_len;
entry_buf += entry->next_entry_offset;
entry_buf_len -= entry->next_entry_offset;
*len_out += entry->next_entry_offset;
*last_offset = &entry->next_entry_offset;
break;
}
if (args->cookie->cookie == COOKIE_DOTDOT ||
args->cookie->cookie == COOKIE_DOT)
ZeroMemory(args->cookie, sizeof(nfs41_readdir_cookie));
out:
return status;
}
static int single_lookup(
IN nfs41_root *root,
IN nfs41_session *session,
IN nfs41_path_fh *parent,
IN const char *filter,
IN bitmap4 *attr_request,
OUT nfs41_readdir_entry *entry)
{
nfs41_abs_path path;
nfs41_path_fh file;
int status;
entry->cookie = 0;
entry->name_len = (uint32_t)strlen(filter) + 1;
StringCbCopyA(entry->name, entry->name_len, filter);
entry->next_entry_offset = 0;
/* format an absolute path 'parent\filter' */
InitializeSRWLock(&path.lock);
abs_path_copy(&path, parent->path);
if (path.len + entry->name_len >= NFS41_MAX_PATH_LEN) {
status = ERROR_BUFFER_OVERFLOW;
goto out;
}
StringCchPrintfA(path.path + path.len,
NFS41_MAX_PATH_LEN - path.len, "\\%s", entry->name);
path.len += (unsigned short)entry->name_len;
path_fh_init(&file, &path);
status = nfs41_lookup(root, session, &path,
NULL, &file, &entry->attr_info, NULL);
if (status) {
dprintf(1, "nfs41_lookup failed with %s\n", nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
out:
return status;
}
int handle_readdir(nfs41_upcall *upcall)
{
int status;
readdir_upcall_args *args = &upcall->args.readdir;
nfs41_open_state *state = args->state;
unsigned char *entry_buf = NULL;
uint32_t entry_buf_len;
bitmap4 attr_request;
bool_t eof;
dprintf(1, "-> handle_nfs41_dirquery(%s,%d,%d,%d)\n",
args->filter, args->initial, args->restart, args->single);
args->buf = NULL;
args->query_reply_len = 0;
if (args->cookie) { /* cookie exists */
if (args->restart) {
dprintf(1, "restarting; clearing previous cookie (%d %p)\n",
args->cookie->cookie, args->cookie);
ZeroMemory(args->cookie, sizeof(nfs41_readdir_cookie));
} else if (args->initial) { /* shouldn't happen */
dprintf(1, "*** initial; clearing previous cookie (%d %p)!\n",
args->cookie->cookie, args->cookie);
ZeroMemory(args->cookie, sizeof(nfs41_readdir_cookie));
} else
dprintf(1, "resuming enumeration with cookie %d.\n",
args->cookie->cookie);
} else { /* cookie is null */
if (args->initial || args->restart) {
dprintf(1, "allocating memory for the 1st readdir cookie\n");
args->cookie = calloc(1, sizeof(nfs41_readdir_cookie));
if (args->cookie == NULL) {
status = GetLastError();
goto out;
}
} else {
dprintf(1, "handle_nfs41_readdir: EOF\n");
status = ERROR_NO_MORE_FILES;
goto out;
}
}
entry_buf = malloc(args->buf_len);
if (entry_buf == NULL) {
status = GetLastError();
goto out_free_cookie;
}
fetch_entries:
entry_buf_len = args->buf_len;
init_getattr_request(&attr_request);
attr_request.arr[0] |= FATTR4_WORD0_RDATTR_ERROR;
if (readdir_has_wildcards((const char*)args->filter)) {
/* use READDIR for wildcards */
uint32_t dots_len = 0;
uint32_t *dots_next_offset = NULL;
if (args->filter[0] == '*' && args->filter[1] == '\0') {
status = readdir_add_dots(args, entry_buf,
entry_buf_len, &dots_len, &dots_next_offset);
if (status)
goto out_free_cookie;
entry_buf_len -= dots_len;
}
if (dots_len && args->single) {
dprintf(2, "skipping nfs41_readdir because the single query "
"will use . or ..\n");
entry_buf_len = 0;
eof = 0;
} else {
dprintf(2, "calling nfs41_readdir with cookie %d %p \n",
args->cookie->cookie, args->cookie);
status = nfs41_readdir(state->session, &state->file,
&attr_request, args->cookie, entry_buf + dots_len,
&entry_buf_len, &eof);
if (status) {
dprintf(1, "nfs41_readdir failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out_free_cookie;
}
}
if (!entry_buf_len && dots_next_offset)
*dots_next_offset = 0;
entry_buf_len += dots_len;
} else {
/* use LOOKUP for single files */
nfs41_readdir_entry *entry = (nfs41_readdir_entry*)entry_buf;
entry->cookie = 0;
entry->name_len = (uint32_t)strlen(args->filter) + 1;
StringCbCopyA(entry->name, entry->name_len, args->filter);
entry->next_entry_offset = 0;
status = single_lookup(args->root, state->session,
&state->file, args->filter, &attr_request, entry);
if (status) {
dprintf(1, "single_lookup failed with %d\n", status);
goto out_free_cookie;
}
entry_buf_len = entry->name_len +
FIELD_OFFSET(nfs41_readdir_entry, name);
eof = 1;
}
status = args->initial ? ERROR_FILE_NOT_FOUND : ERROR_NO_MORE_FILES;
if (entry_buf_len) {
unsigned char *entry_pos = entry_buf;
unsigned char *dst_pos;
uint32_t dst_len = args->buf_len;
nfs41_readdir_entry *entry;
PULONG offset, last_offset = NULL;
if (args->buf == NULL) {
args->buf = malloc(args->buf_len);
if (args->buf == NULL) {
status = GetLastError();
goto out_free_cookie;
}
}
dst_pos = args->buf;
for (;;) {
entry = (nfs41_readdir_entry*)entry_pos;
offset = (PULONG)dst_pos; /* ULONG NextEntryOffset */
dprintf(2, "filter %s looking at %s with cookie %d\n",
args->filter, entry->name, entry->cookie);
if (readdir_filter((const char*)args->filter, entry->name)) {
if (readdir_copy_entry(args, entry, &dst_pos, &dst_len)) {
eof = 0;
dprintf(2, "not enough space to copy entry %s (cookie %d)\n",
entry->name, entry->cookie);
break;
}
last_offset = offset;
status = NO_ERROR;
}
args->cookie->cookie = entry->cookie;
/* last entry we got from the server */
if (!entry->next_entry_offset)
break;
/* we found our single entry, but the server has more */
if (args->single && last_offset) {
eof = 0;
break;
}
entry_pos += entry->next_entry_offset;
}
args->query_reply_len = args->buf_len - dst_len;
if (last_offset) {
*last_offset = 0;
} else if (!eof) {
dprintf(1, "no entries matched; fetch more\n");
goto fetch_entries;
}
}
if (eof) {
dprintf(1, "we don't need to save a cookie\n");
goto out_free_cookie;
} else
dprintf(1, "saving cookie %d %p\n", args->cookie->cookie, args->cookie);
out_free_entry:
free(entry_buf);
out:
dprintf(1, "<- handle_nfs41_dirquery(%s,%d,%d,%d) returning ",
args->filter, args->initial, args->restart, args->single);
if (status) {
switch (status) {
case ERROR_FILE_NOT_FOUND:
dprintf(1, "ERROR_FILE_NOT_FOUND.\n");
break;
case ERROR_NO_MORE_FILES:
dprintf(1, "ERROR_NO_MORE_FILES.\n");
break;
default:
dprintf(1, "error code %d.\n", status);
break;
}
free(args->buf);
args->buf = NULL;
} else {
dprintf(1, "success!\n");
}
return status;
out_free_cookie:
free(args->cookie);
args->cookie = NULL;
goto out_free_entry;
}
int marshall_readdir(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
int status;
readdir_upcall_args *args = &upcall->args.readdir;
status = safe_write(&buffer, length, &args->query_reply_len, sizeof(args->query_reply_len));
if (status) goto out;
status = safe_write(&buffer, length, args->buf, args->query_reply_len);
if (status) goto out;
status = safe_write(&buffer, length, &args->cookie, sizeof(args->cookie));
out:
free(args->buf);
return status;
}

307
daemon/readwrite.c Normal file
View file

@ -0,0 +1,307 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "nfs41_ops.h"
#include "name_cache.h"
#include "upcall.h"
#include "daemon_debug.h"
#include "util.h"
int parse_rw(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
readwrite_upcall_args *args = &upcall->args.rw;
status = safe_read(&buffer, &length, &args->len, sizeof(args->len));
if (status) goto out;
status = safe_read(&buffer, &length, &args->offset, sizeof(args->offset));
if (status) goto out;
status = safe_read(&buffer, &length, &args->buffer, sizeof(args->buffer));
if (status) goto out;
status = safe_read(&buffer, &length, &args->root, sizeof(args->root));
if (status) goto out;
status = safe_read(&buffer, &length, &args->state, sizeof(args->state));
out:
if (status)
eprintf("parsing %s failed with %d\n",
opcode2string(upcall->opcode), status);
else
dprintf(1, "parsing %s len=%ld offset=%ld buf=%p root=%p "
"open_state=0x%p\n", opcode2string(upcall->opcode), args->len,
args->offset, args->buffer, args->root, args->state);
return status;
}
/* NFS41_READ */
static int read_from_mds(
IN nfs41_session *session,
IN stateid4 *stateid,
IN nfs41_path_fh *file,
IN uint64_t offset,
IN uint32_t length,
OUT unsigned char *buffer,
OUT ULONG *len_out)
{
int status = 0;
bool_t eof;
unsigned char *p = buffer;
ULONG to_rcv = length, reloffset = 0, len = 0;
const uint32_t maxreadsize = max_read_size(session, &file->fh);
if (to_rcv > maxreadsize)
dprintf(1, "handle_nfs41_read: reading %d in chunks of %d\n",
to_rcv, maxreadsize);
while(to_rcv > 0) {
uint32_t bytes_read = 0, chunk = min(to_rcv, maxreadsize);
status = nfs41_read(session, file, stateid,
offset + reloffset, chunk, p, &bytes_read, &eof);
if (status && !len) {
status = nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT);
goto out;
}
p += bytes_read;
to_rcv -= bytes_read;
len += bytes_read;
offset += bytes_read;
if (status) {
status = NO_ERROR;
break;
}
if (eof) {
if (!len)
status = ERROR_HANDLE_EOF;
break;
}
}
out:
*len_out = len;
return status;
}
static int read_from_pnfs(
IN nfs41_root *root,
IN nfs41_open_state *state,
IN stateid4 *stateid,
IN uint64_t offset,
IN uint32_t length,
OUT unsigned char *buffer,
OUT ULONG *len_out)
{
pnfs_file_layout *layout;
enum pnfs_status pnfsstat;
int status = NO_ERROR;
pnfsstat = pnfs_open_state_layout(state->session->client->layouts,
state->session, state, PNFS_IOMODE_READ, offset, length, &layout);
if (pnfsstat) {
status = ERROR_NOT_SUPPORTED;
goto out;
}
pnfsstat = pnfs_read(root, state->session, &state->file, stateid,
layout, offset, length, buffer, len_out);
switch (pnfsstat) {
case PNFS_SUCCESS:
break;
case PNFS_READ_EOF:
status = ERROR_HANDLE_EOF;
break;
default:
status = ERROR_READ_FAULT;
break;
}
out:
return status;
}
int handle_read(nfs41_upcall *upcall)
{
stateid4 stateid, *pstateid;
readwrite_upcall_args *args = &upcall->args.rw;
nfs41_open_state *state = args->state;
ULONG pnfs_bytes_read = 0;
int status = NO_ERROR;
pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
if (pstateid == NULL)
pstateid = &state->stateid;
#ifdef PNFS_ENABLE_READ
status = read_from_pnfs(args->root, state, pstateid,
args->offset, args->len, args->buffer, &args->out_len);
if (status == NO_ERROR || status == ERROR_HANDLE_EOF)
goto out;
if (args->out_len) {
pnfs_bytes_read = args->out_len;
args->out_len = 0;
args->offset += pnfs_bytes_read;
args->buffer += pnfs_bytes_read;
args->len -= pnfs_bytes_read;
}
#endif
status = read_from_mds(state->session, pstateid, &state->file,
args->offset, args->len, args->buffer, &args->out_len);
args->out_len += pnfs_bytes_read;
out:
return status;
}
/* NFS41_WRITE */
static int write_to_mds(
IN nfs41_session *session,
IN stateid4 *stateid,
IN nfs41_path_fh *file,
IN uint64_t offset,
IN uint32_t length,
IN unsigned char *buffer,
OUT ULONG *len_out)
{
nfs41_write_verf verf;
enum stable_how4 stable, committed;
unsigned char *p;
const uint32_t maxwritesize = max_write_size(session, &file->fh);
uint32_t to_send, reloffset, len;
int status = 0;
retry_write:
p = buffer;
to_send = length;
reloffset = 0;
len = 0;
stable = to_send <= maxwritesize ? DATA_SYNC4 : UNSTABLE4;
committed = DATA_SYNC4;
if (to_send > maxwritesize)
dprintf(1, "handle_nfs41_write: writing %d in chunks of %d\n",
to_send, maxwritesize);
while(to_send > 0) {
uint32_t bytes_written = 0, chunk = min(to_send, maxwritesize);
status = nfs41_write(session, file, stateid, p, chunk,
offset + reloffset, stable, &bytes_written, &verf);
if (status && !len)
goto out;
p += bytes_written;
to_send -= bytes_written;
len += bytes_written;
reloffset += bytes_written;
if (status) {
status = 0;
break;
}
if (!verify_write(&verf, &committed))
goto retry_write;
}
if (committed == UNSTABLE4) {
dprintf(1, "sending COMMIT for offset=%d and len=%d\n", offset, len);
status = nfs41_commit(session, file, offset, len, 1);
}
out:
*len_out = len;
return nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT);
}
static int write_to_pnfs(
IN nfs41_root *root,
IN nfs41_open_state *state,
IN stateid4 *stateid,
IN uint64_t offset,
IN uint32_t length,
IN unsigned char *buffer,
OUT ULONG *len_out)
{
pnfs_file_layout *layout;
enum pnfs_status pnfsstat;
int status = NO_ERROR;
pnfsstat = pnfs_open_state_layout(state->session->client->layouts,
state->session, state, PNFS_IOMODE_RW, offset, length, &layout);
if (pnfsstat) {
status = ERROR_NOT_SUPPORTED;
goto out;
}
pnfsstat = pnfs_write(root, state->session, &state->file, stateid,
layout, offset, length, buffer, len_out);
if (pnfsstat) {
status = ERROR_WRITE_FAULT;
goto out;
}
out:
return status;
}
int handle_write(nfs41_upcall *upcall)
{
stateid4 stateid, *pstateid = NULL;
readwrite_upcall_args *args = &upcall->args.rw;
nfs41_open_state *state = args->state;
ULONG pnfs_bytes_written = 0;
int status;
pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
if (pstateid == NULL)
pstateid = &state->stateid;
#ifdef PNFS_ENABLE_WRITE
status = write_to_pnfs(args->root, args->state, pstateid,
args->offset, args->len, args->buffer, &args->out_len);
if (status == NO_ERROR)
goto out;
if (args->out_len) {
pnfs_bytes_written = args->out_len;
args->out_len = 0;
args->offset += pnfs_bytes_written;
args->buffer += pnfs_bytes_written;
args->len -= pnfs_bytes_written;
}
#endif
status = write_to_mds(state->session, pstateid, &state->file,
args->offset, args->len, args->buffer, &args->out_len);
args->out_len += pnfs_bytes_written;
out:
return status;
}
int marshall_rw(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
readwrite_upcall_args *args = &upcall->args.rw;
return safe_write(&buffer, length, &args->out_len, sizeof(args->out_len));
}

491
daemon/setattr.c Normal file
View file

@ -0,0 +1,491 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include <strsafe.h>
#include "from_kernel.h"
#include "nfs41_ops.h"
#include "name_cache.h"
#include "upcall.h"
#include "util.h"
#include "daemon_debug.h"
int parse_setattr(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
setattr_upcall_args *args = &upcall->args.setattr;
ZeroMemory(&args->path, sizeof(nfs41_abs_path));
status = get_abs_path(&buffer, &length, &args->path);
if (status) goto out;
status = safe_read(&buffer, &length, &args->set_class, sizeof(args->set_class));
if (status) goto out;
status = safe_read(&buffer, &length, &args->buf_len, sizeof(args->buf_len));
if (status) goto out;
args->buf = malloc(args->buf_len);
if (args->buf == NULL) {
status = GetLastError();
goto out;
}
status = safe_read(&buffer, &length, args->buf, args->buf_len);
if (status) goto out_free;
status = safe_read(&buffer, &length, &args->root, sizeof(args->root));
if (status) goto out_free;
status = safe_read(&buffer, &length, &args->state, sizeof(args->state));
if (status) goto out_free;
status = safe_read(&buffer, &length, &args->open_owner_id, sizeof(ULONG));
if (status) goto out_free;
status = safe_read(&buffer, &length, &args->access_mask, sizeof(ULONG));
if (status) goto out_free;
status = safe_read(&buffer, &length, &args->access_mode, sizeof(ULONG));
out:
if (status)
eprintf("parsing NFS41_FILE_SET failed with %d\n", status);
else
dprintf(1, "parsing NFS41_FILE_SET: filename='%s' info_class=%d "
"buf_len=%d root=%p open_state=%p\nopen_owner_id=%d "
"access_mask=%x access_mode=%x\n", args->path.path, args->set_class,
args->buf_len, args->root, args->state, args->open_owner_id,
args->access_mask, args->access_mode);
return status;
out_free:
free(args->buf);
goto out;
}
static void remove_unsupported_attrs(
IN const bitmap4 *supported_attrs,
IN OUT bitmap4 *attrs)
{
uint32_t i, count = 0;
dprintf(2, "remove_unsupported_attrs\n");
for (i = 0; i < 3; i++) {
dprintf(2, "\tmask[%d] = %12u", i, attrs->arr[i]);
dprintf(2, " & %12u", supported_attrs->arr[i]);
attrs->arr[i] &= supported_attrs->arr[i];
if (attrs->arr[i])
count = i+1;
dprintf(2, " = %12d\n", attrs->arr[i]);
}
attrs->count = min(attrs->count, count);
dprintf(2, "\tcount = %d\n", attrs->count);
}
static int handle_nfs41_setattr(setattr_upcall_args *args)
{
int status;
PFILE_BASIC_INFO basic_info = (PFILE_BASIC_INFO)args->buf;
nfs41_open_state *state = args->state;
nfs41_superblock *superblock = state->file.fh.superblock;
stateid4 stateid, *pstateid;
nfs41_file_info info;
pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
if (pstateid == NULL)
pstateid = &state->stateid;
ZeroMemory(&info, sizeof(info));
/* hidden */
info.hidden = basic_info->FileAttributes & FILE_ATTRIBUTE_HIDDEN ? 1 : 0;
info.attrmask.arr[0] |= FATTR4_WORD0_HIDDEN;
info.attrmask.count = 1;
/* time_create */
if (basic_info->CreationTime.QuadPart > 0) {
file_time_to_nfs_time(&basic_info->CreationTime, &info.time_create);
info.attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE;
info.attrmask.count = 2;
}
/* time_access_set */
if (basic_info->LastAccessTime.QuadPart > 0) {
file_time_to_nfs_time(&basic_info->LastAccessTime, &info.time_access);
info.attrmask.arr[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
info.attrmask.count = 2;
}
/* time_modify_set */
if (basic_info->LastWriteTime.QuadPart > 0) {
file_time_to_nfs_time(&basic_info->LastWriteTime, &info.time_modify);
info.attrmask.arr[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
info.attrmask.count = 2;
}
/* mode */
if (basic_info->FileAttributes & FILE_ATTRIBUTE_READONLY) {
info.mode = 0444;
info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
info.attrmask.count = 2;
}
AcquireSRWLockShared(&superblock->lock);
remove_unsupported_attrs(&superblock->supported_attrs, &info.attrmask);
ReleaseSRWLockShared(&superblock->lock);
if (!info.attrmask.count)
return 0;
status = nfs41_setattr(state->session, &state->file, pstateid, &info);
if (status)
dprintf(1, "nfs41_setattr() failed with error %s.\n",
nfs_error_string(status));
return nfs_to_windows_error(status, ERROR_NOT_SUPPORTED);
}
static int handle_nfs41_remove(setattr_upcall_args *args)
{
nfs41_open_state *state = args->state;
int status;
status = nfs41_remove(state->session, &state->parent,
&state->file.name);
if (status)
dprintf(1, "nfs41_remove() failed with error %s.\n",
nfs_error_string(status));
return nfs_to_windows_error(status, ERROR_ACCESS_DENIED);
}
static void open_state_rename(
OUT nfs41_open_state *state,
IN const nfs41_abs_path *path)
{
AcquireSRWLockExclusive(&state->path.lock);
abs_path_copy(&state->path, path);
last_component(state->path.path, state->path.path + state->path.len,
&state->file.name);
last_component(state->path.path, state->file.name.name,
&state->parent.name);
ReleaseSRWLockExclusive(&state->path.lock);
}
static int handle_nfs41_rename(setattr_upcall_args *args)
{
nfs41_open_state *state = args->state;
PFILE_RENAME_INFO rename = (PFILE_RENAME_INFO)args->buf;
nfs41_abs_path dst_path;
nfs41_path_fh dst_dir;
nfs41_component dst_name, *src_name;
int status;
ZeroMemory(&dst_path, sizeof(dst_path));
src_name = &state->file.name;
if (rename->FileNameLength == 0) {
/* start from state->path instead of args->path, in case we got
* the file from a referred server */
AcquireSRWLockShared(&state->path.lock);
abs_path_copy(&args->path, &state->path);
ReleaseSRWLockShared(&state->path.lock);
path_fh_init(&dst_dir, &args->path);
fh_copy(&dst_dir.fh, &state->parent.fh);
create_silly_rename(&args->path, &state->file.fh, &dst_name);
dprintf(1, "silly rename: %s -> %s\n", src_name->name, dst_name.name);
status = nfs41_rename(state->session,
&state->parent, src_name,
&dst_dir, &dst_name);
if (status) {
dprintf(1, "nfs41_rename() failed with error %s.\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_ACCESS_DENIED);
} else {
/* rename state->path on success */
open_state_rename(state, &args->path);
}
goto out;
}
dst_path.len = (unsigned short)WideCharToMultiByte(CP_UTF8, 0,
rename->FileName, rename->FileNameLength/sizeof(WCHAR),
dst_path.path, NFS41_MAX_PATH_LEN, NULL, NULL);
if (dst_path.len == 0) {
eprintf("WideCharToMultiByte failed to convert destination "
"filename %S.\n", rename->FileName);
status = ERROR_INVALID_PARAMETER;
goto out;
}
path_fh_init(&dst_dir, &dst_path);
/* the destination path is absolute, so start from the root session */
status = nfs41_lookup(args->root, nfs41_root_session(args->root),
&dst_path, &dst_dir, NULL, NULL, NULL);
/* get the components after lookup in case a referral changed its path */
last_component(dst_path.path, dst_path.path + dst_path.len, &dst_name);
last_component(dst_path.path, dst_name.name, &dst_dir.name);
if (status == NO_ERROR) {
if (!rename->ReplaceIfExists) {
status = ERROR_FILE_EXISTS;
goto out;
}
} else if (status != ERROR_FILE_NOT_FOUND) {
dprintf(1, "nfs41_lookup('%s') failed to find destination "
"directory with %d\n", dst_path.path, status);
goto out;
}
/* http://tools.ietf.org/html/rfc5661#section-18.26.3
* "Source and target directories MUST reside on the same
* file system on the server." */
if (state->parent.fh.superblock != dst_dir.fh.superblock) {
status = ERROR_NOT_SAME_DEVICE;
goto out;
}
status = nfs41_rename(state->session,
&state->parent, src_name,
&dst_dir, &dst_name);
if (status) {
dprintf(1, "nfs41_rename() failed with error %s.\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_ACCESS_DENIED);
} else {
/* rename state->path on success */
open_state_rename(state, &dst_path);
}
out:
return status;
}
static int handle_nfs41_set_size(setattr_upcall_args *args)
{
nfs41_open_state *state = args->state;
int status;
/* note: this is called with either FILE_END_OF_FILE_INFO or
* FILE_ALLOCATION_INFO, both of which contain a single LARGE_INTEGER */
PLARGE_INTEGER size = (PLARGE_INTEGER)args->buf;
stateid4 stateid, *pstateid;
nfs41_file_info info;
pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
if (pstateid == NULL)
pstateid = &state->stateid;
ZeroMemory(&info, sizeof(info));
info.size = size->QuadPart;
info.attrmask.count = 1;
info.attrmask.arr[0] = FATTR4_WORD0_SIZE;
dprintf(2, "calling setattr() with size=%lld\n", info.size);
status = nfs41_setattr(state->session, &state->file, pstateid, &info);
if (status)
dprintf(1, "nfs41_setattr() failed with error %s.\n",
nfs_error_string(status));
return status = nfs_to_windows_error(status, ERROR_NOT_SUPPORTED);
}
int handle_nfs41_link(setattr_upcall_args *args)
{
nfs41_open_state *state = args->state;
PFILE_LINK_INFORMATION link = (PFILE_LINK_INFORMATION)args->buf;
nfs41_abs_path dst_path;
nfs41_path_fh dst_dir;
nfs41_component dst_name;
int status;
ZeroMemory(&dst_path, sizeof(dst_path));
dst_path.len = (unsigned short)WideCharToMultiByte(CP_UTF8, 0,
link->FileName, link->FileNameLength/sizeof(WCHAR),
dst_path.path, NFS41_MAX_PATH_LEN, NULL, NULL);
if (dst_path.len == 0) {
eprintf("WideCharToMultiByte failed to convert destination "
"filename %S.\n", link->FileName);
status = ERROR_INVALID_PARAMETER;
goto out;
}
path_fh_init(&dst_dir, &dst_path);
/* the destination path is absolute, so start from the root session */
status = nfs41_lookup(args->root, nfs41_root_session(args->root),
&dst_path, &dst_dir, NULL, NULL, NULL);
/* get the components after lookup in case a referral changed its path */
last_component(dst_path.path, dst_path.path + dst_path.len, &dst_name);
last_component(dst_path.path, dst_name.name, &dst_dir.name);
if (status == NO_ERROR) {
if (!link->ReplaceIfExists) {
status = ERROR_FILE_EXISTS;
goto out;
}
} else if (status != ERROR_FILE_NOT_FOUND) {
dprintf(1, "nfs41_lookup('%s') failed to find destination "
"directory with %d\n", dst_path.path, status);
goto out;
}
/* http://tools.ietf.org/html/rfc5661#section-18.9.3
* "The existing file and the target directory must reside within
* the same file system on the server." */
if (state->file.fh.superblock != dst_dir.fh.superblock) {
status = ERROR_NOT_SAME_DEVICE;
goto out;
}
if (status == NO_ERROR) {
/* LINK will return NFS4ERR_EXIST if the target file exists,
* so we have to remove it ourselves */
status = nfs41_remove(state->session, &dst_dir, &dst_name);
if (status) {
dprintf(1, "nfs41_remove() failed with error %s.\n",
nfs_error_string(status));
status = ERROR_FILE_EXISTS;
goto out;
}
}
status = nfs41_link(state->session, &state->file, &dst_dir, &dst_name);
if (status) {
dprintf(1, "nfs41_link() failed with error %s.\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_INVALID_PARAMETER);
}
out:
return status;
}
int handle_setattr(nfs41_upcall *upcall)
{
setattr_upcall_args *args = &upcall->args.setattr;
nfs41_open_state *state = args->state;
int status;
switch (args->set_class) {
case FileAllocationInformation:
case FileEndOfFileInformation:
if (!state->do_close) {
// get a stateid
uint32_t allow = 0, deny = 0;
StringCchPrintfA((LPSTR)state->owner.owner, NFS4_OPAQUE_LIMIT,
"%u", args->open_owner_id);
state->owner.owner_len = (uint32_t)strlen(
(const char*)state->owner.owner);
map_access_2_allowdeny(args->access_mask, args->access_mode, &allow, &deny);
status = nfs41_open(state->session, allow, deny,
OPEN4_NOCREATE, 0, state, NULL);
if (status) {
dprintf(1, "nfs41_open() failed with %s\n", nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
goto out;
}
state->do_close = 1;
}
}
switch (args->set_class) {
case FileBasicInformation:
status = handle_nfs41_setattr(args);
break;
case FileDispositionInformation:
status = handle_nfs41_remove(args);
break;
case FileRenameInformation:
status = handle_nfs41_rename(args);
break;
case FileAllocationInformation:
case FileEndOfFileInformation:
status = handle_nfs41_set_size(args);
break;
case FileLinkInformation:
status = handle_nfs41_link(args);
break;
default:
eprintf("unknown set_file information class %d\n",
args->set_class);
status = ERROR_NOT_SUPPORTED;
break;
}
out:
free(args->buf);
return status;
}
int marshall_setattr(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
return NO_ERROR;
}
int parse_setexattr(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
setexattr_upcall_args *args = &upcall->args.setexattr;
status = safe_read(&buffer, &length, &args->root, sizeof(args->root));
if (status) goto out;
status = safe_read(&buffer, &length, &args->state, sizeof(args->state));
if (status) goto out;
status = safe_read(&buffer, &length, &args->mode, sizeof(args->mode));
out:
if (status)
eprintf("parsing NFS41_EA_SET failed with %d\n", status);
else
dprintf(1, "parsing NFS41_EA_SET: root=%p open_state=%p mode=%o\n",
args->root, args->state, args->mode);
return status;
}
int handle_setexattr(nfs41_upcall *upcall)
{
int status;
setexattr_upcall_args *args = &upcall->args.setexattr;
nfs41_open_state *state = args->state;
stateid4 stateid, *pstateid;
nfs41_file_info info;
pstateid = nfs41_lock_stateid_copy(&state->last_lock, &stateid);
if (pstateid == NULL)
pstateid = &state->stateid;
ZeroMemory(&info, sizeof(info));
/* mode */
info.mode = args->mode;
info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
info.attrmask.count = 2;
status = nfs41_setattr(state->session, &state->file, pstateid, &info);
if (status)
dprintf(1, "nfs41_setattr() failed with error %s.\n",
nfs_error_string(status));
return nfs_to_windows_error(status, ERROR_NOT_SUPPORTED);
}
int marshall_setexattr(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
return NO_ERROR;
}

24
daemon/sources Normal file
View file

@ -0,0 +1,24 @@
TARGETTYPE=PROGRAM
TARGETNAME=nfsd
SOURCES=nfs41_daemon.c daemon_debug.c nfs41_ops.c nfs41_compound.c nfs41_xdr.c \
nfs41_server.c nfs41_client.c nfs41_superblock.c nfs41_session.c lookup.c \
mount.c open.c readwrite.c lock.c readdir.c getattr.c setattr.c upcall.c \
nfs41_rpc.c util.c pnfs_layout.c pnfs_device.c pnfs_debug.c pnfs_io.c \
name_cache.c namespace.c rbtree.c volume.c callback_server.c callback_xdr.c
UMTYPE=console
USE_LIBCMT=1
#USE_MSVCRT=1
INCLUDES=..\sys;..\dll;..\libtirpc\tirpc
TARGETLIBS=$(SDK_LIB_PATH)\ws2_32.lib $(SDK_LIB_PATH)\iphlpapi.lib \
..\libtirpc\src\obj$(BUILD_ALT_DIR)\*\libtirpc.lib
!IF 0
/W3 is default level
bump to /Wall, but suppress warnings generated by system includes,
as well as the following warnings:
4100 - unused function call arguments (we have lots of stubs)
4127 - constant conditional (I like to use if(0) or if(1))
4220 - varargs matching remaining parameters
4204 - nonstandard extension
!ENDIF
MSC_WARNING_LEVEL=/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4711 /wd4220 /wd4204

222
daemon/upcall.c Normal file
View file

@ -0,0 +1,222 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "upcall.h"
#include "daemon_debug.h"
#include "util.h"
int parse_mount(unsigned char*, uint32_t, nfs41_upcall*);
int handle_mount(nfs41_upcall*);
int marshall_mount(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_unmount(unsigned char*, uint32_t, nfs41_upcall*);
int handle_unmount(nfs41_upcall*);
int marshall_unmount(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_open(unsigned char*, uint32_t, nfs41_upcall*);
int handle_open(nfs41_upcall*);
int marshall_open(unsigned char*, uint32_t*, nfs41_upcall*);
int cancel_open(nfs41_upcall*);
int parse_close(unsigned char*, uint32_t, nfs41_upcall*);
int handle_close(nfs41_upcall*);
int marshall_close(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_rw(unsigned char*, uint32_t, nfs41_upcall*);
int handle_read(nfs41_upcall*);
int handle_write(nfs41_upcall*);
int marshall_rw(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_lock(unsigned char*, uint32_t, nfs41_upcall*);
int handle_lock(nfs41_upcall*);
int marshall_lock(unsigned char*, uint32_t*, nfs41_upcall*);
int cancel_lock(nfs41_upcall*);
int parse_unlock(unsigned char*, uint32_t, nfs41_upcall*);
int handle_unlock(nfs41_upcall*);
int marshall_unlock(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_readdir(unsigned char*, uint32_t, nfs41_upcall*);
int handle_readdir(nfs41_upcall*);
int marshall_readdir(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_getattr(unsigned char*, uint32_t, nfs41_upcall*);
int handle_getattr(nfs41_upcall*);
int marshall_getattr(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_setattr(unsigned char*, uint32_t, nfs41_upcall*);
int handle_setattr(nfs41_upcall*);
int marshall_setattr(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_setexattr(unsigned char*, uint32_t, nfs41_upcall*);
int handle_setexattr(nfs41_upcall*);
int marshall_setexattr(unsigned char*, uint32_t*, nfs41_upcall*);
int parse_volume(unsigned char*, uint32_t, nfs41_upcall*);
int handle_volume(nfs41_upcall*);
int marshall_volume(unsigned char*, uint32_t*, nfs41_upcall*);
static const nfs41_upcall_op g_upcall_op_table[] = {
{ parse_mount, handle_mount, marshall_mount, NULL },
{ parse_unmount, handle_unmount, marshall_unmount, NULL },
{ parse_open, handle_open, marshall_open, cancel_open },
{ parse_close, handle_close, marshall_close, NULL },
{ parse_rw, handle_read, marshall_rw, NULL },
{ parse_rw, handle_write, marshall_rw, NULL },
{ parse_lock, handle_lock, marshall_lock, cancel_lock },
{ parse_unlock, handle_unlock, marshall_unlock, NULL },
{ parse_readdir, handle_readdir, marshall_readdir, NULL },
{ parse_getattr, handle_getattr, marshall_getattr, NULL },
{ parse_setattr, handle_setattr, marshall_setattr, NULL },
{ parse_setexattr, handle_setexattr, marshall_setexattr, NULL },
{ parse_volume, handle_volume, marshall_volume, NULL },
{ NULL, NULL, NULL, NULL }, /* NFS41_SHUTDOWN */
{ NULL, NULL, NULL, NULL }, /* INVALID_OPCODE */
};
static const uint32_t g_upcall_op_table_size = ARRAYSIZE(g_upcall_op_table);
int upcall_parse(
IN unsigned char *buffer,
IN uint32_t length,
OUT nfs41_upcall *upcall)
{
int status;
const nfs41_upcall_op *op;
ZeroMemory(upcall, sizeof(nfs41_upcall));
if (!length) {
eprintf("empty upcall\n");
upcall->status = status = 102;
goto out;
}
dprintf(2, "received %d bytes upcall data: processing upcall\n", length);
print_hexbuf(3, (unsigned char *)"upcall buffer: ", buffer, length);
/* parse common elements */
status = safe_read(&buffer, &length, &upcall->xid, sizeof(uint32_t));
if (status) goto out;
status = safe_read(&buffer, &length, &upcall->opcode, sizeof(uint32_t));
if (status) goto out;
dprintf(2, "xid=%d opcode=%s\n", upcall->xid, opcode2string(upcall->opcode));
if (upcall->opcode >= g_upcall_op_table_size) {
status = ERROR_NOT_SUPPORTED;
eprintf("unrecognized upcall opcode %d!\n", upcall->opcode);
goto out;
}
/* parse the operation's arguments */
op = &g_upcall_op_table[upcall->opcode];
if (op->parse) {
status = op->parse(buffer, length, upcall);
if (status) {
eprintf("parsing of upcall '%s' failed with %d.\n",
opcode2string(upcall->opcode), status);
goto out;
}
}
out:
return status;
}
int upcall_handle(
IN nfs41_upcall *upcall)
{
int status = NO_ERROR;
const nfs41_upcall_op *op;
op = &g_upcall_op_table[upcall->opcode];
if (op->handle == NULL) {
status = ERROR_NOT_SUPPORTED;
eprintf("upcall '%s' missing handle function!\n",
opcode2string(upcall->opcode));
goto out;
}
upcall->status = op->handle(upcall);
out:
return status;
}
int upcall_marshall(
IN nfs41_upcall *upcall,
OUT unsigned char *buffer,
IN uint32_t length,
OUT uint32_t *length_out)
{
int status = NO_ERROR;
const nfs41_upcall_op *op;
unsigned char *orig_buf = buffer;
const uint32_t total = length, orig_len = length;
/* marshall common elements */
write_downcall:
length = orig_len;
buffer = orig_buf;
safe_write(&buffer, &length, &upcall->xid, sizeof(upcall->xid));
safe_write(&buffer, &length, &upcall->opcode, sizeof(upcall->opcode));
safe_write(&buffer, &length, &upcall->status, sizeof(upcall->status));
safe_write(&buffer, &length, &upcall->last_error, sizeof(upcall->last_error));
if (upcall->status)
goto out;
/* marshall the operation's results */
op = &g_upcall_op_table[upcall->opcode];
if (op->marshall == NULL) {
status = ERROR_NOT_SUPPORTED;
eprintf("upcall '%s' missing marshall function!\n",
opcode2string(upcall->opcode));
upcall->status = status;
goto write_downcall;
}
status = op->marshall(buffer, &length, upcall);
if (status) {
upcall->status = status;
goto write_downcall;
}
out:
*length_out = total - length;
return status;
}
int upcall_cancel(
IN nfs41_upcall *upcall)
{
int status = NO_ERROR;
const nfs41_upcall_op *op;
op = &g_upcall_op_table[upcall->opcode];
if (op->cancel)
status = op->cancel(upcall);
return status;
}

201
daemon/upcall.h Normal file
View file

@ -0,0 +1,201 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_DAEMON_UPCALL_H__
#define __NFS41_DAEMON_UPCALL_H__
#include "nfs41_ops.h"
/* structures for upcall arguments */
typedef struct __mount_upcall_args {
char srv_name[UPCALL_BUF_SIZE];
nfs41_abs_path path;
nfs41_root *root;
} mount_upcall_args;
typedef struct __unmount_upcall_args {
nfs41_root *root;
} unmount_upcall_args;
typedef struct __open_upcall_args {
nfs41_abs_path path;
FILE_BASIC_INFO basic_info;
FILE_STANDARD_INFO std_info;
nfs41_root *root;
nfs41_open_state *state;
ULONG access_mask;
ULONG access_mode;
ULONG file_attrs;
ULONG disposition;
ULONG create_opts;
ULONG open_owner_id;
DWORD mode;
LONGLONG changeattr;
BOOLEAN created;
} open_upcall_args;
typedef struct __close_upcall_args {
nfs41_abs_path path;
nfs41_root *root;
nfs41_open_state *state;
BOOLEAN remove;
BOOLEAN renamed;
} close_upcall_args;
typedef struct __readwrite_upcall_args {
nfs41_root *root;
nfs41_open_state *state;
unsigned char *buffer;
LONGLONG offset;
ULONG len;
ULONG out_len;
} readwrite_upcall_args;
typedef struct __lock_upcall_args {
nfs41_open_state *state;
nfs41_root *root;
LONGLONG offset;
LONGLONG length;
BOOLEAN exclusive;
BOOLEAN blocking;
} lock_upcall_args;
typedef struct __unlock_upcall_args {
nfs41_open_state *state;
nfs41_root *root;
uint32_t count;
unsigned char *buf;
uint32_t buf_len;
} unlock_upcall_args;
typedef struct __getattr_upcall_args {
FILE_BASIC_INFO basic_info;
FILE_STANDARD_INFO std_info;
FILE_ATTRIBUTE_TAG_INFO tag_info;
nfs41_root *root;
nfs41_open_state *state;
int query_class;
int buf_len;
int query_reply_len;
} getattr_upcall_args;
typedef struct __setattr_upcall_args {
nfs41_abs_path path;
nfs41_root *root;
nfs41_open_state *state;
unsigned char *buf;
uint32_t buf_len;
int set_class;
ULONG open_owner_id;
ULONG access_mask;
ULONG access_mode;
} setattr_upcall_args;
typedef struct __setexattr_upcall_args {
nfs41_root *root;
nfs41_open_state *state;
uint32_t mode;
} setexattr_upcall_args;
typedef struct __readdir_upcall_args {
char filter[UPCALL_BUF_SIZE];
FILE_BASIC_INFO basic_info;
FILE_STANDARD_INFO std_info;
FILE_ATTRIBUTE_TAG_INFO tag_info;
nfs41_readdir_cookie *cookie;
nfs41_root *root;
nfs41_open_state *state;
unsigned char *buf;
int buf_len;
int query_class;
int query_reply_len;
BOOLEAN initial;
BOOLEAN restart;
BOOLEAN single;
} readdir_upcall_args;
typedef struct __volume_upcall_args {
nfs41_root *root;
ULONGLONG total;
ULONGLONG user;
ULONGLONG avail;
} volume_upcall_args;
typedef union __upcall_args {
mount_upcall_args mount;
unmount_upcall_args unmount;
open_upcall_args open;
close_upcall_args close;
readwrite_upcall_args rw;
lock_upcall_args lock;
unlock_upcall_args unlock;
getattr_upcall_args getattr;
setattr_upcall_args setattr;
setexattr_upcall_args setexattr;
readdir_upcall_args readdir;
volume_upcall_args volume;
} upcall_args;
typedef struct __nfs41_upcall {
uint32_t xid;
uint32_t opcode;
uint32_t status;
uint32_t last_error;
upcall_args args;
} nfs41_upcall;
/* upcall operation interface */
typedef int (*upcall_parse_proc)(unsigned char*, uint32_t, nfs41_upcall*);
typedef int (*upcall_handle_proc)(nfs41_upcall*);
typedef int (*upcall_marshall_proc)(unsigned char*, uint32_t*, nfs41_upcall*);
typedef int (*upcall_cancel_proc)(nfs41_upcall*);
typedef struct __nfs41_upcall_op {
upcall_parse_proc parse;
upcall_handle_proc handle;
upcall_marshall_proc marshall;
upcall_cancel_proc cancel;
} nfs41_upcall_op;
/* upcall.c */
int upcall_parse(
IN unsigned char *buffer,
IN uint32_t length,
OUT nfs41_upcall *upcall);
int upcall_handle(
IN nfs41_upcall *upcall);
int upcall_marshall(
IN nfs41_upcall *upcall,
OUT unsigned char *buffer,
IN uint32_t length,
OUT uint32_t *length_out);
int upcall_cancel(
IN nfs41_upcall *upcall);
#endif /* !__NFS41_DAEMON_UPCALL_H__ */

450
daemon/util.c Normal file
View file

@ -0,0 +1,450 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <strsafe.h>
#include <stdio.h>
#include <stdlib.h>
#include "daemon_debug.h"
#include "util.h"
#include "nfs41_ops.h"
int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len)
{
if (*remaining < dest_len)
return ERROR_BUFFER_OVERFLOW;
CopyMemory(dest, *pos, dest_len);
*pos += dest_len;
*remaining -= dest_len;
return 0;
}
int safe_write(unsigned char **pos, uint32_t *remaining, void *src, uint32_t src_len)
{
if (*remaining < src_len)
return ERROR_BUFFER_OVERFLOW;
CopyMemory(*pos, src, src_len);
*pos += src_len;
*remaining -= src_len;
return 0;
}
int wchar2asci(WCHAR *src, char **dest, int dest_len)
{
int len = 0;
len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
if (*dest == NULL) {
*dest = malloc(len + 1);
if (*dest == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
} else if (len > dest_len)
return ERROR_BUFFER_OVERFLOW;
WideCharToMultiByte(CP_UTF8, 0, src, len, *dest, len + 1, NULL, NULL);
return 0;
}
int get_name(unsigned char **pos, uint32_t *remaining, char *out_name)
{
WCHAR name[UPCALL_BUF_SIZE];
int status, len = 0;
status = safe_read(pos, remaining, &len, sizeof(USHORT));
if (status) goto out;
status = safe_read(pos, remaining, name, len);
if (status) goto out;
name[len/sizeof(WCHAR)] = L'\0';
status = wchar2asci(name, &out_name, UPCALL_BUF_SIZE);
out:
return status;
}
int get_abs_path(unsigned char **pos, uint32_t *remaining, nfs41_abs_path *path)
{
int status = get_name(pos, remaining, path->path);
path->len = status ? 0 : (unsigned short)strlen(path->path);
return status;
}
const char* strip_path(
IN const char *path,
OUT uint32_t *len_out)
{
const char *name = strrchr(path, '\\');
name = name ? name + 1 : path;
if (len_out)
*len_out = (uint32_t)strlen(name);
return name;
}
uint32_t max_read_size(
IN const nfs41_session *session,
IN const nfs41_fh *fh)
{
const uint32_t maxresponse = session->fore_chan_attrs.ca_maxresponsesize;
return (uint32_t)min(fh->superblock->maxread, maxresponse - READ_OVERHEAD);
}
uint32_t max_write_size(
IN const nfs41_session *session,
IN const nfs41_fh *fh)
{
const uint32_t maxrequest = session->fore_chan_attrs.ca_maxrequestsize;
return (uint32_t)min(fh->superblock->maxwrite, maxrequest - WRITE_OVERHEAD);
}
bool_t verify_write(
IN nfs41_write_verf *verf,
IN OUT enum stable_how4 *stable)
{
if (verf->committed != UNSTABLE4) {
*stable = verf->committed;
dprintf(3, "verify_write: committed to stable storage\n");
return 1;
}
if (*stable != UNSTABLE4) {
memcpy(verf->expected, verf->verf, NFS4_VERIFIER_SIZE);
*stable = UNSTABLE4;
dprintf(3, "verify_write: first unstable write, saving verifier\n");
return 1;
}
if (memcmp(verf->expected, verf->verf, NFS4_VERIFIER_SIZE) == 0) {
dprintf(3, "verify_write: verifier matches expected\n");
return 1;
}
dprintf(2, "verify_write: verifier changed; writes have been lost!\n");
return 0;
}
ULONG nfs_file_info_to_attributes(
IN const nfs41_file_info *info)
{
ULONG attrs = 0;
if (info->type == NF4DIR)
attrs |= FILE_ATTRIBUTE_DIRECTORY;
else if (info->type != NF4REG)
dprintf(1, "unhandled file type %d, defaulting to NF4REG\n",
info->type);
if (info->mode == 0444) /* XXX: 0444 for READONLY */
attrs |= FILE_ATTRIBUTE_READONLY;
/* TODO: FILE_ATTRIBUTE_HIDDEN */
// FILE_ATTRIBUTE_NORMAL attribute is only set if no other attributes are present.
// all other override this value.
return attrs ? attrs : FILE_ATTRIBUTE_NORMAL;
}
void nfs_to_basic_info(
IN const nfs41_file_info *info,
OUT PFILE_BASIC_INFO basic_out)
{
nfs_time_to_file_time(&info->time_create, &basic_out->CreationTime);
nfs_time_to_file_time(&info->time_access, &basic_out->LastAccessTime);
nfs_time_to_file_time(&info->time_modify, &basic_out->LastWriteTime);
/* XXX: was using 'change' attr, but that wasn't giving a time */
nfs_time_to_file_time(&info->time_modify, &basic_out->ChangeTime);
basic_out->FileAttributes = nfs_file_info_to_attributes(info);
}
void nfs_to_standard_info(
IN const nfs41_file_info *info,
OUT PFILE_STANDARD_INFO std_out)
{
std_out->AllocationSize.QuadPart =
std_out->EndOfFile.QuadPart = (LONGLONG)info->size;
std_out->NumberOfLinks = info->numlinks;
std_out->DeletePending = FALSE;
std_out->Directory = info->type == NF4DIR ? TRUE : FALSE;
}
/* http://msdn.microsoft.com/en-us/library/ms724290%28VS.85%29.aspx:
* A file time is a 64-bit value that represents the number of
* 100-nanosecond intervals that have elapsed since 12:00 A.M.
* January 1, 1601 Coordinated Universal Time (UTC). */
static __inline void get_file_epoch(
OUT PLARGE_INTEGER time_out)
{
static const SYSTEMTIME jan_1_1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
SystemTimeToFileTime(&jan_1_1970, (LPFILETIME)time_out);
}
void file_time_to_nfs_time(
IN const PLARGE_INTEGER file_time,
OUT nfstime4 *nfs_time)
{
LARGE_INTEGER diff;
get_file_epoch(&diff);
diff.QuadPart = file_time->QuadPart - diff.QuadPart;
nfs_time->seconds = diff.QuadPart / 10000000;
nfs_time->nseconds = (uint32_t)((diff.QuadPart % 10000000)*100);
}
void nfs_time_to_file_time(
IN const nfstime4 *nfs_time,
OUT PLARGE_INTEGER file_time)
{
LARGE_INTEGER diff;
get_file_epoch(&diff);
file_time->QuadPart = diff.QuadPart +
nfs_time->seconds * 10000000 +
nfs_time->nseconds / 100;
}
void get_file_time(
OUT PLARGE_INTEGER file_time)
{
GetSystemTimeAsFileTime((LPFILETIME)file_time);
}
void get_nfs_time(
OUT nfstime4 *nfs_time)
{
LARGE_INTEGER file_time;
get_file_time(&file_time);
file_time_to_nfs_time(&file_time, nfs_time);
}
void map_access_2_allowdeny(ULONG access_mask, ULONG access_mode,
uint32_t *allow, uint32_t *deny)
{
if ((access_mask & FILE_WRITE_DATA) &&
((access_mask & FILE_READ_DATA) ||
(access_mask & FILE_EXECUTE)))
*allow = OPEN4_SHARE_ACCESS_BOTH;
else if ((access_mask & FILE_READ_DATA) ||
(access_mask & FILE_EXECUTE))
*allow = OPEN4_SHARE_ACCESS_READ;
else if (access_mask & FILE_WRITE_DATA ||
(access_mask & FILE_APPEND_DATA) ||
(access_mask & FILE_WRITE_ATTRIBUTES))
*allow = OPEN4_SHARE_ACCESS_WRITE;
#define FIX_ALLOW_DENY_WIN2NFS_CONVERSION
#ifdef FIX_ALLOW_DENY_WIN2NFS_CONVERSION
if ((access_mode & FILE_SHARE_READ) &&
(access_mode & FILE_SHARE_WRITE))
*deny = OPEN4_SHARE_DENY_NONE;
else if (access_mode & FILE_SHARE_READ)
*deny = OPEN4_SHARE_DENY_WRITE;
else if (access_mode & FILE_SHARE_WRITE)
*deny = OPEN4_SHARE_DENY_READ;
else
*deny = OPEN4_SHARE_DENY_BOTH;
#else
// AGLO: 11/13/2009.
// readonly file that is being opened for reading with a
// share read mode given above logic translates into deny
// write and linux server does not allow it.
*deny = OPEN4_SHARE_DENY_NONE;
#endif
}
bool_t multi_addr_find(
IN const multi_addr4 *addrs,
IN const netaddr4 *addr,
OUT OPTIONAL uint32_t *index_out)
{
uint32_t i;
for (i = 0; i < addrs->count; i++) {
const netaddr4 *saddr = &addrs->arr[i];
if (!strncmp(saddr->netid, addr->netid, NFS41_NETWORK_ID_LEN) &&
!strncmp(saddr->uaddr, addr->uaddr, NFS41_UNIVERSAL_ADDR_LEN)) {
if (index_out) *index_out = i;
return 1;
}
}
return 0;
}
int nfs_to_windows_error(int status, int default_error)
{
/* make sure this is actually an nfs error */
if (status < 0 || (status > 70 && status < 10001) || status > 10087) {
eprintf("nfs_to_windows_error called with non-nfs "
"error code %d; returning the error as is\n", status);
return status;
}
switch (status) {
case NFS4_OK: return NO_ERROR;
case NFS4ERR_PERM: return ERROR_ACCESS_DENIED;
case NFS4ERR_NOENT: return ERROR_FILE_NOT_FOUND;
case NFS4ERR_IO: return ERROR_NET_WRITE_FAULT;
case NFS4ERR_ACCESS: return ERROR_ACCESS_DENIED;
case NFS4ERR_EXIST: return ERROR_FILE_EXISTS;
case NFS4ERR_XDEV: return ERROR_NOT_SAME_DEVICE;
case NFS4ERR_INVAL: return ERROR_INVALID_PARAMETER;
case NFS4ERR_FBIG: return ERROR_FILE_TOO_LARGE;
case NFS4ERR_NOSPC: return ERROR_DISK_FULL;
case NFS4ERR_ROFS: return ERROR_NETWORK_ACCESS_DENIED;
case NFS4ERR_MLINK: return ERROR_TOO_MANY_LINKS;
case NFS4ERR_NAMETOOLONG: return ERROR_FILENAME_EXCED_RANGE;
case NFS4ERR_STALE: return ERROR_NETNAME_DELETED;
case NFS4ERR_NOTEMPTY: return ERROR_NOT_EMPTY;
case NFS4ERR_DENIED: return ERROR_LOCK_FAILED;
case NFS4ERR_TOOSMALL: return ERROR_BUFFER_OVERFLOW;
case NFS4ERR_LOCKED: return ERROR_LOCK_VIOLATION;
case NFS4ERR_SHARE_DENIED: return ERROR_SHARING_VIOLATION;
case NFS4ERR_LOCK_RANGE: return ERROR_NOT_LOCKED;
case NFS4ERR_ATTRNOTSUPP: return ERROR_NOT_SUPPORTED;
case NFS4ERR_OPENMODE: return ERROR_ACCESS_DENIED;
case NFS4ERR_LOCK_NOTSUPP: return ERROR_ATOMIC_LOCKS_NOT_SUPPORTED;
case NFS4ERR_BADCHAR:
case NFS4ERR_BADNAME: return ERROR_INVALID_NAME;
case NFS4ERR_NOTDIR:
case NFS4ERR_ISDIR:
case NFS4ERR_SYMLINK:
case NFS4ERR_WRONG_TYPE: return ERROR_INVALID_PARAMETER;
case NFS4ERR_OLD_STATEID:
case NFS4ERR_BAD_STATEID:
case NFS4ERR_ADMIN_REVOKED: return ERROR_FILE_INVALID;
default:
dprintf(1, "nfs error %s not mapped to windows error; "
"returning default error %d\n",
nfs_error_string(status), default_error);
return default_error;
}
}
bool_t next_component(
IN const char *path,
IN const char *path_end,
OUT nfs41_component *component)
{
const char *component_end;
component->name = next_non_delimiter(path, path_end);
component_end = next_delimiter(component->name, path_end);
component->len = (unsigned short)(component_end - component->name);
return component->len > 0;
}
bool_t last_component(
IN const char *path,
IN const char *path_end,
OUT nfs41_component *component)
{
const char *component_end = prev_delimiter(path_end, path);
component->name = prev_non_delimiter(component_end, path);
component->name = prev_delimiter(component->name, path);
component->name = next_non_delimiter(component->name, component_end);
component->len = (unsigned short)(component_end - component->name);
return component->len > 0;
}
bool_t is_last_component(
IN const char *path,
IN const char *path_end)
{
path = next_delimiter(path, path_end);
return next_non_delimiter(path, path_end) == path_end;
}
void abs_path_copy(
OUT nfs41_abs_path *dst,
IN const nfs41_abs_path *src)
{
dst->len = src->len;
StringCchCopyNA(dst->path, NFS41_MAX_PATH_LEN, src->path, dst->len);
}
void path_fh_init(
OUT nfs41_path_fh *file,
IN nfs41_abs_path *path)
{
file->path = path;
last_component(path->path, path->path + path->len, &file->name);
}
void fh_copy(
OUT nfs41_fh *dst,
IN const nfs41_fh *src)
{
dst->fileid = src->fileid;
dst->superblock = src->superblock;
dst->len = src->len;
memcpy(dst->fh, src->fh, dst->len);
}
void path_fh_copy(
OUT nfs41_path_fh *dst,
IN const nfs41_path_fh *src)
{
dst->path = src->path;
if (dst->path) {
const size_t name_start = src->name.name - src->path->path;
dst->name.name = dst->path->path + name_start;
dst->name.len = src->name.len;
} else {
dst->name.name = NULL;
dst->name.len = 0;
}
fh_copy(&dst->fh, &src->fh);
}
int create_silly_rename(
IN nfs41_abs_path *path,
IN const nfs41_fh *fh,
OUT nfs41_component *silly)
{
const char *end = path->path + NFS41_MAX_PATH_LEN;
const unsigned short extra_len = 2 + 2*(unsigned short)fh->len;
char name[NFS41_MAX_COMPONENT_LEN+1];
char *tmp;
uint32_t i;
int status = NO_ERROR;
if (path->len + extra_len >= NFS41_MAX_PATH_LEN) {
status = ERROR_BUFFER_OVERFLOW;
goto out;
}
last_component(path->path, path->path + path->len, silly);
StringCchCopyNA(name, NFS41_MAX_COMPONENT_LEN+1, silly->name, silly->len);
tmp = (char*)silly->name;
StringCchPrintf(tmp, end - tmp, ".%s.", name);
tmp += silly->len + 2;
for (i = 0; i < fh->len; i++, tmp += 2)
StringCchPrintf(tmp, end - tmp, "%02x", fh->fh[i]);
path->len += extra_len;
silly->len += extra_len;
out:
return status;
}

166
daemon/util.h Normal file
View file

@ -0,0 +1,166 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_DAEMON_UTIL_H__
#define __NFS41_DAEMON_UTIL_H__
#include "nfs41_types.h"
struct __nfs41_session;
struct __nfs41_write_verf;
enum stable_how4;
int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len);
int safe_write(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len);
int get_name(unsigned char **pos, uint32_t *remaining, char *out_name);
int get_abs_path(unsigned char **pos, uint32_t *remaining, nfs41_abs_path *path);
int wchar2asci(WCHAR *src, char **dest, int dest_len);
const char* strip_path(
IN const char *path,
OUT uint32_t *len_out OPTIONAL);
uint32_t max_read_size(
IN const struct __nfs41_session *session,
IN const nfs41_fh *fh);
uint32_t max_write_size(
IN const struct __nfs41_session *session,
IN const nfs41_fh *fh);
bool_t verify_write(
IN struct __nfs41_write_verf *verf,
IN OUT enum stable_how4 *stable);
ULONG nfs_file_info_to_attributes(
IN const nfs41_file_info *info);
void nfs_to_basic_info(
IN const nfs41_file_info *info,
OUT PFILE_BASIC_INFO basic_out);
void nfs_to_standard_info(
IN const nfs41_file_info *info,
OUT PFILE_STANDARD_INFO std_out);
void file_time_to_nfs_time(
IN const PLARGE_INTEGER file_time,
OUT nfstime4 *nfs_time);
void nfs_time_to_file_time(
IN const nfstime4 *nfs_time,
OUT PLARGE_INTEGER file_time);
void get_file_time(
OUT PLARGE_INTEGER file_time);
void get_nfs_time(
OUT nfstime4 *nfs_time);
int create_silly_rename(
IN nfs41_abs_path *path,
IN const nfs41_fh *fh,
OUT nfs41_component *silly);
void map_access_2_allowdeny(
IN ULONG access_mask,
IN ULONG access_mode,
OUT uint32_t *allow,
OUT uint32_t *deny);
bool_t multi_addr_find(
IN const multi_addr4 *addrs,
IN const netaddr4 *addr,
OUT OPTIONAL uint32_t *index_out);
/* nfs_to_windows_error
* Returns a windows ERROR_ code corresponding to the given NFS4ERR_ status.
* If the status is outside the range of valid NFS4ERR_ values, it is returned
* unchanged. Otherwise, if the status does not match a value in the mapping,
* a debug warning is generated and the default_error value is returned.
*/
int nfs_to_windows_error(int status, int default_error);
__inline uint32_t align8(uint32_t offset) {
return 8 + ((offset - 1) & ~7);
}
__inline uint32_t align4(uint32_t offset) {
return 4 + ((offset - 1) & ~3);
}
/* path parsing */
__inline int is_delimiter(char c) {
return c == '\\' || c == '/' || c == '\0';
}
__inline const char* next_delimiter(const char *pos, const char *end) {
while (pos < end && !is_delimiter(*pos))
pos++;
return pos;
}
__inline const char* prev_delimiter(const char *pos, const char *start) {
while (pos > start && !is_delimiter(*pos))
pos--;
return pos;
}
__inline const char* next_non_delimiter(const char *pos, const char *end) {
while (pos < end && is_delimiter(*pos))
pos++;
return pos;
}
__inline const char* prev_non_delimiter(const char *pos, const char *start) {
while (pos > start && is_delimiter(*pos))
pos--;
return pos;
}
bool_t next_component(
IN const char *path,
IN const char *path_end,
OUT nfs41_component *component);
bool_t last_component(
IN const char *path,
IN const char *path_end,
OUT nfs41_component *component);
bool_t is_last_component(
IN const char *path,
IN const char *path_end);
void abs_path_copy(
OUT nfs41_abs_path *dst,
IN const nfs41_abs_path *src);
void path_fh_init(
OUT nfs41_path_fh *file,
IN nfs41_abs_path *path);
void fh_copy(
OUT nfs41_fh *dst,
IN const nfs41_fh *src);
void path_fh_copy(
OUT nfs41_path_fh *dst,
IN const nfs41_path_fh *src);
__inline int valid_handle(HANDLE handle) {
return handle != INVALID_HANDLE_VALUE && handle != 0;
}
#endif /* !__NFS41_DAEMON_UTIL_H__ */

86
daemon/volume.c Normal file
View file

@ -0,0 +1,86 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <stdio.h>
#include "nfs41_ops.h"
#include "from_kernel.h"
#include "upcall.h"
#include "util.h"
#include "daemon_debug.h"
int parse_volume(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
{
int status;
volume_upcall_args *args = &upcall->args.volume;
status = safe_read(&buffer, &length, &args->root, sizeof(HANDLE));
if (status)
eprintf("parsing NFS41_VOLUME_QUERY failed with %d\n",
status);
else
dprintf(1, "parsing NFS41_VOLUME_QUERY: root=0x%p\n", args->root);
return status;
}
int handle_volume(nfs41_upcall *upcall)
{
nfs41_file_info info = { 0 };
bitmap4 attr_request = { 2, { 0, FATTR4_WORD1_SPACE_AVAIL |
FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL } };
volume_upcall_args *args = &upcall->args.volume;
int status;
/* query the space_ attributes of the root filesystem */
status = nfs41_getattr(nfs41_root_session(args->root),
NULL, &attr_request, &info);
if (status) {
eprintf("nfs41_getattr() failed with %s\n",
nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
goto out;
}
args->total = info.space_total; /* total disk space in bytes */
args->user = info.space_avail; /* bytes available to this user */
args->avail = info.space_free; /* free disk space in bytes */
dprintf(2, "Volume: %llu user, %llu free of %llu total\n",
args->user, args->avail, args->total);
out:
return status;
}
int marshall_volume(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
{
int status;
volume_upcall_args *args = &upcall->args.volume;
status = safe_write(&buffer, length, &args->total, sizeof(args->total));
if (status) goto out;
status = safe_write(&buffer, length, &args->user, sizeof(args->user));
if (status) goto out;
status = safe_write(&buffer, length, &args->avail, sizeof(args->avail));
out:
return status;
}

1
dirs Normal file
View file

@ -0,0 +1 @@
DIRS = dll sys mount daemon libtirpc install

76
dll/dllmain.c Normal file
View file

@ -0,0 +1,76 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
/*++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
dllmain.c
Abstract:
This module implements the initialization routines for network
provider interface
Notes:
This module has been built and tested only in UNICODE environment
--*/
#include <windows.h>
#include <process.h>
// NOTE:
//
// Function:` DllMain
//
// Return: TRUE => Success
// FALSE => Failure
BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
{
BOOL bStatus = TRUE;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return(bStatus);
}

8
dll/makefile Normal file
View file

@ -0,0 +1,8 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

900
dll/nfs41_np.c Normal file
View file

@ -0,0 +1,900 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <windows.h>
#include <npapi.h>
#include <devioctl.h>
#include <strsafe.h>
#include "nfs41_driver.h"
#include "nfs41_np.h"
#include "options.h"
#ifdef DBG
#define DbgP(_x_) NFS41DbgPrint _x_
#else
#define DbgP(_x_)
#endif
#define TRACE_TAG L"[NFS41_NP]"
#define WNNC_DRIVER( major, minor ) ( major * 0x00010000 + minor )
ULONG _cdecl NFS41DbgPrint( __in LPTSTR Format, ... )
{
ULONG rc = 0;
TCHAR szbuffer[256];
va_list marker;
va_start( marker, Format );
{
//StringCchVPrintfW( szbuffer, 127, Format, marker );
StringCchVPrintfW( szbuffer, 256, Format, marker );
szbuffer[255] = (TCHAR)0;
OutputDebugString( TRACE_TAG );
OutputDebugString( szbuffer );
}
return rc;
}
int filter(unsigned int code)
{
DbgP((L"####Got exception %u\n", code));
return EXCEPTION_CONTINUE_SEARCH;
}
DWORD
OpenSharedMemory(
PHANDLE phMutex,
PHANDLE phMemory,
PVOID *pMemory)
/*++
Routine Description:
This routine opens the shared memory for exclusive manipulation
Arguments:
phMutex - the mutex handle
phMemory - the memory handle
pMemory - a ptr. to the shared memory which is set if successful
Return Value:
WN_SUCCESS -- if successful
--*/
{
DWORD dwStatus;
*phMutex = 0;
*phMemory = 0;
*pMemory = NULL;
*phMutex = OpenMutex(SYNCHRONIZE,
FALSE,
TEXT(NFS41NP_MUTEX_NAME));
if (*phMutex == NULL)
{
dwStatus = GetLastError();
DbgP((TEXT("OpenSharedMemory: OpenMutex failed\n")));
goto OpenSharedMemoryAbort1;
}
WaitForSingleObject(*phMutex, INFINITE);
*phMemory = OpenFileMapping(FILE_MAP_WRITE,
FALSE,
TEXT(NFS41_USER_SHARED_MEMORY_NAME));
if (*phMemory == NULL)
{
dwStatus = GetLastError();
DbgP((TEXT("OpenSharedMemory: OpenFileMapping failed\n")));
goto OpenSharedMemoryAbort2;
}
*pMemory = MapViewOfFile(*phMemory, FILE_MAP_WRITE, 0, 0, 0);
if (*pMemory == NULL)
{
dwStatus = GetLastError();
DbgP((TEXT("OpenSharedMemory: MapViewOfFile failed\n")));
goto OpenSharedMemoryAbort3;
}
return ERROR_SUCCESS;
OpenSharedMemoryAbort3:
CloseHandle(*phMemory);
OpenSharedMemoryAbort2:
ReleaseMutex(*phMutex);
CloseHandle(*phMutex);
*phMutex = NULL;
OpenSharedMemoryAbort1:
DbgP((TEXT("OpenSharedMemory: return dwStatus: %d\n"), dwStatus));
return dwStatus;
}
VOID
CloseSharedMemory(
PHANDLE hMutex,
PHANDLE hMemory,
PVOID *pMemory)
/*++
Routine Description:
This routine relinquishes control of the shared memory after exclusive
manipulation
Arguments:
hMutex - the mutex handle
hMemory - the memory handle
pMemory - a ptr. to the shared memory which is set if successful
Return Value:
--*/
{
if (*pMemory)
{
UnmapViewOfFile(*pMemory);
*pMemory = NULL;
}
if (*hMemory)
{
CloseHandle(*hMemory);
*hMemory = 0;
}
if (*hMutex)
{
if (ReleaseMutex(*hMutex) == FALSE)
{
DbgP((TEXT("CloseSharedMemory: ReleaseMutex error: %d\n"), GetLastError()));
}
CloseHandle(*hMutex);
*hMutex = 0;
}
}
static DWORD StoreConnectionInfo(
IN LPCWSTR LocalName,
IN LPCWSTR ConnectionName,
IN USHORT ConnectionNameLength,
IN LPNETRESOURCE lpNetResource)
{
DWORD status;
HANDLE hMutex, hMemory;
PNFS41NP_SHARED_MEMORY pSharedMemory;
PNFS41NP_NETRESOURCE pNfs41NetResource;
INT Index;
BOOLEAN FreeEntryFound = FALSE;
status = OpenSharedMemory(&hMutex, &hMemory, &(PVOID)pSharedMemory);
if (status)
goto out;
DbgP((TEXT("StoreConnectionInfo: NextIndex %d, NumResources %d\n"),
pSharedMemory->NextAvailableIndex,
pSharedMemory->NumberOfResourcesInUse));
for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
{
if (!pSharedMemory->NetResources[Index].InUse)
{
FreeEntryFound = TRUE;
DbgP((TEXT("Reusing existing index %d\n"), Index));
break;
}
}
if (!FreeEntryFound)
{
if (pSharedMemory->NextAvailableIndex >= NFS41NP_MAX_DEVICES) {
status = WN_NO_MORE_DEVICES;
goto out_close;
}
Index = pSharedMemory->NextAvailableIndex++;
DbgP((TEXT("Using new index %d\n"), Index));
}
pSharedMemory->NumberOfResourcesInUse += 1;
pNfs41NetResource = &pSharedMemory->NetResources[Index];
pNfs41NetResource->InUse = TRUE;
pNfs41NetResource->dwScope = lpNetResource->dwScope;
pNfs41NetResource->dwType = lpNetResource->dwType;
pNfs41NetResource->dwDisplayType = lpNetResource->dwDisplayType;
pNfs41NetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
pNfs41NetResource->LocalNameLength = (USHORT)(wcslen(LocalName) + 1) * sizeof(WCHAR);
pNfs41NetResource->RemoteNameLength = (USHORT)(wcslen(lpNetResource->lpRemoteName) + 1) * sizeof(WCHAR);
pNfs41NetResource->ConnectionNameLength = ConnectionNameLength;
StringCchCopy(pNfs41NetResource->LocalName,
pNfs41NetResource->LocalNameLength,
LocalName);
StringCchCopy(pNfs41NetResource->RemoteName,
pNfs41NetResource->RemoteNameLength,
lpNetResource->lpRemoteName);
StringCchCopy(pNfs41NetResource->ConnectionName,
pNfs41NetResource->ConnectionNameLength,
ConnectionName);
// TODO: copy mount options -cbodley
out_close:
CloseSharedMemory(&hMutex, &hMemory, &(PVOID)pSharedMemory);
out:
return status;
}
ULONG
SendTo_NFS41Driver(
IN ULONG IoctlCode,
IN PVOID InputDataBuf,
IN ULONG InputDataLen,
IN PVOID OutputDataBuf,
IN PULONG pOutputDataLen)
{
HANDLE DeviceHandle; // The mini rdr device handle
BOOL rc = FALSE;
ULONG Status;
Status = WN_SUCCESS;
DbgP((L"[aglo] calling CreateFile\n"));
DeviceHandle = CreateFile(
NFS41_USER_DEVICE_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
(HANDLE) NULL );
DbgP((L"[aglo] after CreateFile Device Handle\n"));
if ( INVALID_HANDLE_VALUE != DeviceHandle )
{
__try {
DbgP((L"[aglo] calling DeviceIoControl\n"));
rc = DeviceIoControl(
DeviceHandle,
IoctlCode,
InputDataBuf,
InputDataLen,
OutputDataBuf,
*pOutputDataLen,
pOutputDataLen,
NULL );
} __except(filter(GetExceptionCode())) {
DbgP((L"#### In except\n"));
}
DbgP((L"[aglo] returned from DeviceIoControl %08lx\n", rc));
if ( !rc )
{
DbgP((L"[aglo] SendTo_NFS41Driver: returning error from DeviceIoctl\n"));
Status = GetLastError( );
}
else
{
DbgP((L"[aglo] SendTo_NFS41Driver: The DeviceIoctl call succeded\n"));
}
CloseHandle(DeviceHandle);
}
else
{
Status = GetLastError( );
DbgP((L"[aglo] SendTo_NFS41Driver: error %08lx opening device \n", Status));
}
DbgP((L"[aglo] returned from SendTo_NFS41Driver %08lx\n", Status));
return Status;
}
DWORD APIENTRY
NPGetCaps(
DWORD nIndex )
{
DWORD rc = 0;
DbgP(( L"[aglo] GetNetCaps %d\n", nIndex ));
switch ( nIndex )
{
case WNNC_SPEC_VERSION:
rc = WNNC_SPEC_VERSION51;
break;
case WNNC_NET_TYPE:
rc = WNNC_NET_RDR2SAMPLE;
break;
case WNNC_DRIVER_VERSION:
rc = WNNC_DRIVER(1, 0);
break;
case WNNC_CONNECTION:
rc = WNNC_CON_GETCONNECTIONS |
WNNC_CON_CANCELCONNECTION |
WNNC_CON_ADDCONNECTION |
WNNC_CON_ADDCONNECTION3;
break;
case WNNC_ENUMERATION:
rc = WNNC_ENUM_LOCAL;
break;
case WNNC_START:
rc = 1;
break;
case WNNC_USER:
case WNNC_DIALOG:
case WNNC_ADMIN:
default:
rc = 0;
break;
}
return rc;
}
DWORD APIENTRY
NPLogonNotify(
__in PLUID lpLogonId,
__in PCWSTR lpAuthentInfoType,
__in PVOID lpAuthentInfo,
__in PCWSTR lpPreviousAuthentInfoType,
__in PVOID lpPreviousAuthentInfo,
__in PWSTR lpStationName,
__in PVOID StationHandle,
__out PWSTR *lpLogonScript)
{
*lpLogonScript = NULL;
DbgP(( L"[aglo] NPLogonNotify: returning WN_SUCCESS\n" ));
return WN_SUCCESS;
}
DWORD APIENTRY
NPPasswordChangeNotify (
__in LPCWSTR lpAuthentInfoType,
__in LPVOID lpAuthentInfo,
__in LPCWSTR lpPreviousAuthentInfoType,
__in LPVOID lpPreviousAuthentInfo,
__in LPWSTR lpStationName,
LPVOID StationHandle,
DWORD dwChangeInfo )
{
DbgP(( L"[aglo] NPPasswordChangeNotify: WN_NOT_SUPPORTED\n" ));
SetLastError( WN_NOT_SUPPORTED );
return WN_NOT_SUPPORTED;
}
DWORD APIENTRY
NPAddConnection(
__in LPNETRESOURCE lpNetResource,
__in_opt LPWSTR lpPassword,
__in_opt LPWSTR lpUserName )
{
return NPAddConnection3( NULL, lpNetResource, lpPassword, lpUserName, 0 );
}
DWORD APIENTRY
NPAddConnection3(
__in HWND hwndOwner,
__in LPNETRESOURCE lpNetResource,
__in_opt LPWSTR lpPassword,
__in_opt LPWSTR lpUserName,
__in DWORD dwFlags)
{
DWORD Status;
WCHAR wszScratch[128];
WCHAR LocalName[3];
DWORD CopyBytes = 0;
CONNECTION_INFO Connection;
LPWSTR ConnectionName;
WCHAR ServerName[MAX_PATH];
PWCHAR p;
DWORD i;
DbgP(( L"[aglo] NPAddConnection3('%s', '%s')\n",
lpNetResource->lpLocalName, lpNetResource->lpRemoteName ));
Status = InitializeConnectionInfo(&Connection,
(PMOUNT_OPTION_BUFFER)lpNetResource->lpComment,
&ConnectionName);
if (Status) {
DbgP(( L"InitializeConnectionInfo failed with %d\n", Status ));
goto out;
}
// \device\miniredirector\;<DriveLetter>:\Server\Share
// local name, must start with "X:"
if (lstrlen(lpNetResource->lpLocalName) < 2 ||
lpNetResource->lpLocalName[1] != L':') {
Status = WN_BAD_LOCALNAME;
goto out;
}
LocalName[0] = (WCHAR) toupper(lpNetResource->lpLocalName[0]);
LocalName[1] = L':';
LocalName[2] = L'\0';
StringCchCopyW( ConnectionName, MAX_PATH, NFS41_DEVICE_NAME );
StringCchCatW( ConnectionName, MAX_PATH, L"\\;" );
StringCchCatW( ConnectionName, MAX_PATH, LocalName );
// remote name, must start with "\\"
if (lpNetResource->lpRemoteName[0] == L'\0' ||
lpNetResource->lpRemoteName[0] != L'\\' ||
lpNetResource->lpRemoteName[1] != L'\\') {
Status = WN_BAD_NETNAME;
goto out;
}
/* note: remotename comes as \\server but we need to add \server thus +1 pointer */
p = lpNetResource->lpRemoteName + 1;
ServerName[0] = L'\\';
i = 1;
for(;;) {
/* convert servername ending unix slash to windows slash */
if (p[i] == L'/')
p[i] = L'\\';
/* deal with servername ending with any slash */
if (p[i] == L'\0')
p[i] = L'\\';
ServerName[i] = p[i];
if (p[i] == L'\\') break;
i++;
}
ServerName[i] = L'\0';
StringCchCatW( ConnectionName, MAX_PATH, ServerName);
/* insert the "nfs4" in between the server name and the path,
* just to make sure all calls to our driver come thru this */
StringCchCatW( ConnectionName, MAX_PATH, L"\\nfs4" );
#ifdef CONVERT_2_UNIX_SLASHES
/* convert all windows slashes to unix slashes */
{
PWCHAR q = p;
DWORD j = 0;
for(;;) {
if(q[j] == L'\0') break;
if (q[j] == L'\\') q[j] = L'/';
j++;
}
}
#else
/* convert all unix slashes to windows slashes */
{
PWCHAR q = p;
DWORD j = 0;
for(;;) {
if(q[j] == L'\0') break;
if (q[j] == L'/') q[j] = L'\\';
j++;
}
}
#endif
StringCchCatW( ConnectionName, MAX_PATH, &p[i]);
DbgP(( L"[aglo] Full Connect Name: %s\n", ConnectionName ));
DbgP(( L"[aglo] Full Connect Name Length: %d %d\n",
(wcslen(ConnectionName) + 1) * sizeof(WCHAR),
(lstrlen(ConnectionName) + 1) * sizeof(WCHAR)));
if ( QueryDosDevice( LocalName, wszScratch, 128 )
|| GetLastError() != ERROR_FILE_NOT_FOUND) {
Status = WN_ALREADY_CONNECTED;
goto out;
}
MarshalConnectionInfo(&Connection);
Status = SendTo_NFS41Driver( IOCTL_NFS41_ADDCONN,
Connection.Buffer, Connection.BufferSize,
NULL, &CopyBytes );
if (Status) {
DbgP(( L"[aglo] SendTo_NFS41Driver failed with %d\n", Status));
Status = WN_BAD_NETNAME;
goto out;
}
DbgP(( L"[aglo] calling DefineDosDevice\n"));
if ( !DefineDosDevice( DDD_RAW_TARGET_PATH |
DDD_NO_BROADCAST_SYSTEM,
lpNetResource->lpLocalName,
ConnectionName ) ) {
Status = GetLastError();
DbgP(( L"[aglo] DefineDosDevice failed with %d\n", Status));
goto out_delconn;
}
// The connection was established and the local device mapping
// added. Include this in the list of mapped devices.
Status = StoreConnectionInfo(LocalName, ConnectionName,
Connection.Buffer->NameLength, lpNetResource);
if (Status) {
DbgP(( L"[aglo] StoreConnectionInfo failed with %d\n", Status));
goto out_undefine;
}
out:
FreeConnectionInfo(&Connection);
DbgP(( L"[aglo] NPAddConnection3: status %08X\n", Status));
return Status;
out_undefine:
DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH |
DDD_EXACT_MATCH_ON_REMOVE, LocalName, ConnectionName);
out_delconn:
SendTo_NFS41Driver(IOCTL_NFS41_DELCONN, ConnectionName,
Connection.Buffer->NameLength, NULL, &CopyBytes);
goto out;
}
DWORD APIENTRY
NPCancelConnection(
__in LPWSTR lpName,
__in BOOL fForce )
{
DWORD Status = 0;
HANDLE hMutex, hMemory;
PNFS41NP_SHARED_MEMORY pSharedMemory;
DbgP((TEXT("NPCancelConnection\n")));
DbgP((TEXT("NPCancelConnection: ConnectionName: %S\n"), lpName));
Status = OpenSharedMemory( &hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS)
{
INT Index;
PNFS41NP_NETRESOURCE pNetResource;
Status = WN_NOT_CONNECTED;
DbgP((TEXT("NPCancelConnection: NextIndex %d, NumResources %d\n"),
pSharedMemory->NextAvailableIndex,
pSharedMemory->NumberOfResourcesInUse));
for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
{
pNetResource = &pSharedMemory->NetResources[Index];
if (pNetResource->InUse)
{
if ( ( (wcslen(lpName) + 1) * sizeof(WCHAR) ==
pNetResource->LocalNameLength)
&& ( !wcscmp(lpName, pNetResource->LocalName) ))
{
ULONG CopyBytes;
DbgP((TEXT("NPCancelConnection: Connection Found:\n")));
CopyBytes = 0;
Status = SendTo_NFS41Driver( IOCTL_NFS41_DELCONN,
pNetResource->ConnectionName,
pNetResource->ConnectionNameLength,
NULL,
&CopyBytes );
if (Status != WN_SUCCESS)
{
DbgP((TEXT("NPCancelConnection: SendToMiniRdr returned Status %lx\n"),Status));
break;
}
if (DefineDosDevice(DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
lpName,
pNetResource->ConnectionName) == FALSE)
{
DbgP((TEXT("RemoveDosDevice: DefineDosDevice error: %d\n"), GetLastError()));
Status = GetLastError();
}
else
{
pNetResource->InUse = FALSE;
pSharedMemory->NumberOfResourcesInUse--;
if (Index+1 == pSharedMemory->NextAvailableIndex)
pSharedMemory->NextAvailableIndex--;
}
break;
}
DbgP((TEXT("NPCancelConnection: Name %S EntryName %S\n"),
lpName,pNetResource->LocalName));
DbgP((TEXT("NPCancelConnection: Name Length %d Entry Name Length %d\n"),
pNetResource->LocalNameLength,pNetResource->LocalName));
}
}
CloseSharedMemory( &hMutex,
&hMemory,
(PVOID)&pSharedMemory);
}
return Status;
}
DWORD APIENTRY
NPGetConnection(
__in LPWSTR lpLocalName,
__out_bcount(*lpBufferSize) LPWSTR lpRemoteName,
__inout LPDWORD lpBufferSize )
{
DWORD Status = 0;
HANDLE hMutex, hMemory;
PNFS41NP_SHARED_MEMORY pSharedMemory;
Status = OpenSharedMemory( &hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS)
{
INT Index;
PNFS41NP_NETRESOURCE pNetResource;
Status = WN_NOT_CONNECTED;
for (Index = 0; Index < pSharedMemory->NextAvailableIndex; Index++)
{
pNetResource = &pSharedMemory->NetResources[Index];
if (pNetResource->InUse)
{
if ( ( (wcslen(lpLocalName) + 1) * sizeof(WCHAR) ==
pNetResource->LocalNameLength)
&& ( !wcscmp(lpLocalName, pNetResource->LocalName) ))
{
if (*lpBufferSize < pNetResource->RemoteNameLength)
{
*lpBufferSize = pNetResource->RemoteNameLength;
Status = WN_MORE_DATA;
}
else
{
*lpBufferSize = pNetResource->RemoteNameLength;
CopyMemory( lpRemoteName,
pNetResource->RemoteName,
pNetResource->RemoteNameLength);
Status = WN_SUCCESS;
}
break;
}
}
}
CloseSharedMemory( &hMutex, &hMemory, (PVOID)&pSharedMemory);
}
return Status;
}
DWORD APIENTRY
NPOpenEnum(
DWORD dwScope,
DWORD dwType,
DWORD dwUsage,
LPNETRESOURCE lpNetResource,
LPHANDLE lphEnum )
{
DWORD Status;
DbgP((L"[aglo] NPOpenEnum\n"));
*lphEnum = NULL;
switch ( dwScope )
{
case RESOURCE_CONNECTED:
{
*lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( ULONG ) );
if (*lphEnum )
{
Status = WN_SUCCESS;
}
else
{
Status = WN_OUT_OF_MEMORY;
}
break;
}
break;
case RESOURCE_CONTEXT:
default:
Status = WN_NOT_SUPPORTED;
break;
}
DbgP((L"[aglo] NPOpenEnum returning Status %lx\n",Status));
return(Status);
}
DWORD APIENTRY
NPEnumResource(
HANDLE hEnum,
LPDWORD lpcCount,
LPVOID lpBuffer,
LPDWORD lpBufferSize)
{
DWORD Status = WN_SUCCESS;
ULONG EntriesCopied;
LPNETRESOURCE pNetResource;
ULONG SpaceNeeded = 0;
ULONG SpaceAvailable;
PWCHAR StringZone;
HANDLE hMutex, hMemory;
PNFS41NP_SHARED_MEMORY pSharedMemory;
PNFS41NP_NETRESOURCE pNfsNetResource;
INT Index = *(PULONG)hEnum;
DbgP((L"[aglo] NPEnumResource\n"));
DbgP((L"[aglo] NPEnumResource Count Requested %d\n", *lpcCount));
pNetResource = (LPNETRESOURCE) lpBuffer;
SpaceAvailable = *lpBufferSize;
EntriesCopied = 0;
StringZone = (PWCHAR) ((PBYTE)lpBuffer + *lpBufferSize);
Status = OpenSharedMemory( &hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if ( Status == WN_SUCCESS)
{
Status = WN_NO_MORE_ENTRIES;
for (Index = *(PULONG)hEnum; Index < pSharedMemory->NextAvailableIndex; Index++)
{
pNfsNetResource = &pSharedMemory->NetResources[Index];
if (pNfsNetResource->InUse)
{
SpaceNeeded = sizeof( NETRESOURCE );
SpaceNeeded += pNfsNetResource->LocalNameLength;
SpaceNeeded += pNfsNetResource->RemoteNameLength;
SpaceNeeded += 5 * sizeof(WCHAR); // comment
SpaceNeeded += sizeof(NFS41_PROVIDER_NAME_U); // provider name
if ( SpaceNeeded > SpaceAvailable )
{
Status = WN_MORE_DATA;
DbgP((L"[aglo] NPEnumResource More Data Needed - %d\n", SpaceNeeded));
*lpBufferSize = SpaceNeeded;
break;
}
else
{
SpaceAvailable -= SpaceNeeded;
pNetResource->dwScope = pNfsNetResource->dwScope;
pNetResource->dwType = pNfsNetResource->dwType;
pNetResource->dwDisplayType = pNfsNetResource->dwDisplayType;
pNetResource->dwUsage = pNfsNetResource->dwUsage;
// setup string area at opposite end of buffer
SpaceNeeded -= sizeof( NETRESOURCE );
StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
// copy local name
StringCchCopy( StringZone,
pNfsNetResource->LocalNameLength,
pNfsNetResource->LocalName );
pNetResource->lpLocalName = StringZone;
StringZone += pNfsNetResource->LocalNameLength/sizeof(WCHAR);
// copy remote name
StringCchCopy( StringZone,
pNfsNetResource->RemoteNameLength,
pNfsNetResource->RemoteName );
pNetResource->lpRemoteName = StringZone;
StringZone += pNfsNetResource->RemoteNameLength/sizeof(WCHAR);
// copy comment
pNetResource->lpComment = StringZone;
*StringZone++ = L'A';
*StringZone++ = L'_';
*StringZone++ = L'O';
*StringZone++ = L'K';
*StringZone++ = L'\0';
// copy provider name
pNetResource->lpProvider = StringZone;
StringCbCopyW( StringZone, sizeof(NFS41_PROVIDER_NAME_U), NFS41_PROVIDER_NAME_U );
StringZone += sizeof(NFS41_PROVIDER_NAME_U)/sizeof(WCHAR);
EntriesCopied++;
if(EntriesCopied >= *lpcCount)
{
Status = WN_SUCCESS;
break;
}
// set new bottom of string zone
StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
}
pNetResource++;
}
}
CloseSharedMemory( &hMutex, &hMemory, (PVOID*)&pSharedMemory);
}
*lpcCount = EntriesCopied;
*(PULONG) hEnum = Index;
DbgP((L"[aglo] NPEnumResource entries returned: %d\n", EntriesCopied));
return Status;
}
DWORD APIENTRY
NPCloseEnum(
HANDLE hEnum )
{
DbgP((L"[aglo] NPCloseEnum\n"));
HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum );
return WN_SUCCESS;
}
DWORD APIENTRY
NPGetResourceParent(
LPNETRESOURCE lpNetResource,
LPVOID lpBuffer,
LPDWORD lpBufferSize )
{
DbgP(( L"[aglo] NPGetResourceParent: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}
DWORD APIENTRY
NPGetResourceInformation(
__in LPNETRESOURCE lpNetResource,
__out_bcount(*lpBufferSize) LPVOID lpBuffer,
__inout LPDWORD lpBufferSize,
__deref_out LPWSTR *lplpSystem )
{
DbgP(( L"[aglo] NPGetResourceInformation: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}
DWORD APIENTRY
NPGetUniversalName(
LPCWSTR lpLocalPath,
DWORD dwInfoLevel,
LPVOID lpBuffer,
LPDWORD lpBufferSize )
{
DbgP(( L"[aglo] NPGetUniversalName: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}

17
dll/nfs41_np.def Normal file
View file

@ -0,0 +1,17 @@
SECTIONS .NFS41_NP READ WRITE SHARED
EXPORTS
NPGetCaps @13
NPAddConnection @17
NPAddConnection3 @38
NPCancelConnection @18
NPGetConnection @12
NPOpenEnum @33
NPEnumResource @34
NPCloseEnum @35
NPGetUniversalName @40
NPGetResourceParent @41
NPGetResourceInformation @52
NPLogonNotify @500
NPPasswordChangeNotify @501

52
dll/nfs41_np.h Normal file
View file

@ -0,0 +1,52 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_NP_H__
#define __NFS41_NP_H__
#define NFS41NP_MUTEX_NAME "NFS41NPMUTEX"
#define NFS41NP_MAX_DEVICES 26
typedef struct __NFS41NP_NETRESOURCE {
BOOL InUse;
USHORT LocalNameLength;
USHORT RemoteNameLength;
USHORT ConnectionNameLength;
DWORD dwScope;
DWORD dwType;
DWORD dwDisplayType;
DWORD dwUsage;
WCHAR LocalName[MAX_PATH];
WCHAR RemoteName[MAX_PATH];
WCHAR ConnectionName[MAX_PATH];
WCHAR Options[MAX_PATH];
} NFS41NP_NETRESOURCE, *PNFS41NP_NETRESOURCE;
typedef struct __NFS41NP_SHARED_MEMORY {
INT NextAvailableIndex;
INT NumberOfResourcesInUse;
NFS41NP_NETRESOURCE NetResources[NFS41NP_MAX_DEVICES];
} NFS41NP_SHARED_MEMORY, *PNFS41NP_SHARED_MEMORY;
#endif /* !__NFS41_NP_H__ */

100
dll/options.c Normal file
View file

@ -0,0 +1,100 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include "options.h"
DWORD InitializeConnectionInfo(
IN OUT PCONNECTION_INFO Connection,
IN PMOUNT_OPTION_BUFFER Options,
OUT LPWSTR *ConnectionName)
{
DWORD result = WN_SUCCESS;
SIZE_T size;
/* verify that this is a mount options buffer */
if (Options &&
Options->Zero == 0 &&
Options->Secret == MOUNT_OPTION_BUFFER_SECRET)
{
Connection->Options = Options;
size = MAX_CONNECTION_BUFFER_SIZE(Options->Length);
}
else
{
Connection->Options = NULL;
size = MAX_CONNECTION_BUFFER_SIZE(0);
}
Connection->Buffer = LocalAlloc(LMEM_ZEROINIT, size);
if (Connection->Buffer)
*ConnectionName = (LPWSTR)Connection->Buffer->Buffer;
else
result = WN_OUT_OF_MEMORY;
return result;
}
static FORCEINLINE SIZE_T ConnectionBufferSize(
IN PCONNECTION_BUFFER Buffer)
{
return sizeof(USHORT) + sizeof(USHORT) + sizeof(ULONG) +
Buffer->NameLength + Buffer->EaPadding + Buffer->EaLength;
}
void MarshalConnectionInfo(
IN OUT PCONNECTION_INFO Connection)
{
PCONNECTION_BUFFER Buffer = Connection->Buffer;
LPWSTR ConnectionName = (LPWSTR)Buffer->Buffer;
Buffer->NameLength = (USHORT)(wcslen(ConnectionName) + 1) * sizeof(WCHAR);
/* copy the EaBuffer after the end of ConnectionName */
if (Connection->Options && Connection->Options->Length)
{
PBYTE ptr = Buffer->Buffer + Buffer->NameLength;
/* add padding so EaBuffer starts on a ULONG boundary */
Buffer->EaPadding = (USHORT)
(sizeof(ULONG) - (SIZE_T)ptr % sizeof(ULONG)) % sizeof(ULONG);
Buffer->EaLength = Connection->Options->Length;
ptr += Buffer->EaPadding;
RtlCopyMemory(ptr, Connection->Options->Buffer, Buffer->EaLength);
}
Connection->BufferSize = (ULONG)ConnectionBufferSize(Buffer);
}
void FreeConnectionInfo(
IN PCONNECTION_INFO Connection)
{
if (Connection->Buffer)
{
LocalFree(Connection->Buffer);
Connection->Buffer = NULL;
}
Connection->Options = NULL;
Connection->BufferSize = 0;
}

84
dll/options.h Normal file
View file

@ -0,0 +1,84 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_NP_OPTIONS_H__
#define __NFS41_NP_OPTIONS_H__
#define MOUNT_OPTION_BUFFER_SECRET ('n4')
/* MOUNT_OPTION_BUFFER
* The mount options buffer received by NPAddConnection3
* via NETRESOURCE.lpComment. To avoid interpreting a normal
* comment string as mount options, a NULL and secret number
* are expected at the front. */
typedef struct _MOUNT_OPTION_BUFFER {
USHORT Zero; /* = 0 */
USHORT Secret; /* = 'n4' */
ULONG Length;
BYTE Buffer[1];
} MOUNT_OPTION_BUFFER, *PMOUNT_OPTION_BUFFER;
/* CONNECTION_BUFFER
* The connection information as sent to the driver via
* IOCTL_NFS41_ADDCONN. The buffer contains the connection name
* followed by any extended attributes for mount options. */
typedef struct _CONNECTION_BUFFER {
USHORT NameLength; /* length of connection filename */
USHORT EaPadding; /* 0-3 bytes of padding to put EaBuffer
* on a ULONG boundary */
ULONG EaLength; /* length of EaBuffer */
BYTE Buffer[1];
} CONNECTION_BUFFER, *PCONNECTION_BUFFER;
/* CONNECTION_INFO
* Used in NPAddConnection3 to encapsulate the formation of
* the connection buffer. */
typedef struct _CONNECTION_INFO {
PMOUNT_OPTION_BUFFER Options;
ULONG BufferSize;
PCONNECTION_BUFFER Buffer;
} CONNECTION_INFO, *PCONNECTION_INFO;
#define MAX_CONNECTION_BUFFER_SIZE(EaSize) ( \
sizeof(CONNECTION_BUFFER) + MAX_PATH + (EaSize) )
/* options.c */
DWORD InitializeConnectionInfo(
IN OUT PCONNECTION_INFO Connection,
IN PMOUNT_OPTION_BUFFER Options,
OUT LPWSTR *ConnectionName);
void FreeConnectionInfo(
IN OUT PCONNECTION_INFO Connection);
/* MarshallConnectionInfo
* Prepares the CONNECTION_BUFFER for transmission to the driver
* by copying the extended attributes into place and updating the
* lengths accordingly. */
void MarshalConnectionInfo(
IN OUT PCONNECTION_INFO Connection);
#endif /* !__NFS41_NP_OPTIONS_H__ */

21
dll/sources Normal file
View file

@ -0,0 +1,21 @@
TARGETTYPE=DYNLINK
TARGETNAME=nfs41_np
SOURCES=dllmain.c nfs41_np.c options.c
UMTYPE=console
UNICODE=1
DLLBASE=0x1010000
USE_NTDLL=1
NET_C_DEFINES=-DUNICODE
INCLUDES=..\sys; \
$(DDK_INC_PATH);
TARGETLIBS=$(DDK_LIB_PATH)\user32.lib $(DDK_LIB_PATH)\kernel32.lib
DLLDEF=nfs41_np.def
!IF 0
/W3 is default level
bump to /Wall, but suppress warnings generated by system includes,
as well as the following warnings:
4100 - unused function call arguments (we have lots of stubs)
4127 - constant conditional (I like to use if(0) or if(1))
!ENDIF
MSC_WARNING_LEVEL=/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4711

2
install.bat Normal file
View file

@ -0,0 +1,2 @@
nfs_install.exe
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 132 ./nfs41rdr.inf

47
install/nfs_install.c Normal file
View file

@ -0,0 +1,47 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
/*
*
* This file is just for prepending nfs41_driver to the
* correct regestry entry
*
*/
#include <tchar.h>
#include "nfs41_driver.h"
#include "nfsreginst.h"
void __cdecl _tmain(int argc, TCHAR *argv[])
{
if(argc == 1 || atoi(argv[1]) == 1)
{
RdrSetupProviderOrder();
}
else
{
while( RdrRemoveProviderFromOrder() ) {};
}
return;
}

652
install/nfsreginst.c Normal file
View file

@ -0,0 +1,652 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
/*++
Module Name:
nfsreginst.c
--*/
#include "nfsreginst.h"
REGENTRY ProviderOrderKeyValues[] =
{
{ TEXT("ProviderOrder"), REG_SZ, 0, 0 }
};
BOOL RdrSetupProviderOrder( void )
{
LPTSTR pOrderString = NULL;
ULONG_PTR len;
BOOL success = TRUE;
LPTSTR pNewOrderString;
while( RdrRemoveProviderFromOrder() ) {};
len = RdrGetProviderOrderString( &pOrderString ) * sizeof(TCHAR);
if ( len > 0 && pOrderString )
{
len += sizeof( PROVIDER_NAME ) + (2 * sizeof(TCHAR)); // add 2 for comma delimeter and null
pNewOrderString = malloc( len );
if ( pNewOrderString )
{
StringCbCopy( pNewOrderString, len, PROVIDER_NAME );
StringCbCat( pNewOrderString, len, TEXT(",") );
StringCbCat( pNewOrderString, len, pOrderString );
success = RdrSetProviderOrderString( pNewOrderString );
free( pNewOrderString );
}
}
else
{
success = RdrSetProviderOrderString( PROVIDER_NAME );
}
if ( pOrderString )
{
free( pOrderString );
}
return success;
}
ULONG_PTR RdrGetProviderOrderString( __out LPTSTR *OrderString )
{
HKEY hOrderKey;
ULONG_PTR len = 0;
if ( OpenKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
{
ReadRegistryKeyValues( hOrderKey,
sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
ProviderOrderKeyValues);
RegCloseKey(hOrderKey);
len = ProviderOrderKeyValues[0].dwLength / sizeof( TCHAR ) - 1;
*OrderString = (LPTSTR) ProviderOrderKeyValues[0].pvValue;
}
return len;
}
BOOL RdrSetProviderOrderString( __in LPTSTR OrderString )
{
HKEY hOrderKey;
BOOL rc = FALSE;
if ( CreateKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
{
ProviderOrderKeyValues[0].dwLength = ( lstrlen( OrderString ) + 1 ) * sizeof( TCHAR );
ProviderOrderKeyValues[0].pvValue = OrderString;
WriteRegistryKeyValues( hOrderKey,
sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
ProviderOrderKeyValues);
RegCloseKey(hOrderKey);
rc = TRUE;
}
return rc;
}
BOOL RdrRemoveProviderFromOrder( void )
{
LPTSTR pCompare, OrderString, pOrig, Provider = PROVIDER_NAME;
BOOL match = FALSE;
ULONG_PTR len = 0;
len = RdrGetProviderOrderString( &pOrig );
OrderString = pOrig;
if ( OrderString && Provider && *Provider )
{
pCompare = Provider;
while ( *OrderString )
{
if ( toupper(*OrderString) != toupper(*pCompare++) )
{
pCompare = Provider;
while ( ( *OrderString != TEXT(',') ) && ( *OrderString != TEXT('\0') ) )
{
OrderString++;
}
}
if ( *OrderString != TEXT('\0') ) OrderString++;
if ( *pCompare == TEXT('\0') )
{
if ( ( *OrderString == TEXT(',') ) || ( *OrderString == TEXT('\0') ) )
{
LPTSTR pNewString;
pNewString = malloc( len ); //Yes, this is a little larger than necessary
//No, I don't care that much
StringCchCopy(pNewString, len, pOrig);
//if ((DWORD_PTR)OrderString - (DWORD_PTR)pOrig - (DWORD_PTR)pCompare + (DWORD_PTR)Provider == 0 ) OrderString += 1;
if ( *OrderString == TEXT(',') )
{
StringCchCopy(pNewString + (DWORD_PTR)OrderString - (DWORD_PTR)pOrig - (DWORD_PTR)pCompare + (DWORD_PTR)Provider, len, OrderString + 1);
}
else
{
StringCchCopy(pNewString + (DWORD_PTR)OrderString - (DWORD_PTR)pOrig - (DWORD_PTR)pCompare + (DWORD_PTR)Provider - 1, len, OrderString);
}
match = RdrSetProviderOrderString( pNewString );
free(pNewString);
break;
}
else // hmm, it's a substring of another provider name
{
while ( ( *OrderString != TEXT(',') ) && ( *OrderString != TEXT('\0') ) )
{
OrderString++;
}
pCompare = Provider;
}
}
}
}
free( pOrig );
return match;
}
void
ReadRegistryKeyValues(
HKEY hCurrentKey,
DWORD NumberOfValues,
PREGENTRY pValues)
/*++
Routine Description:
This routine reads a bunch of values associated with a given key.
Arguments:
hCurrentKey - the key
NumberOfValues - the number of values
pValues - the array of values
Return Value:
None
--*/
{
//
// Iterate through table reading the values along the way
//
DWORD i;
for (i = 0; i < NumberOfValues; i++)
{
DWORD dwType;
LPTSTR pszKey;
dwType = pValues[i].dwType;
pszKey = pValues[i].pszKey;
switch (dwType)
{
case REG_SZ:
GetRegsz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_DWORD:
GetRegdw(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_EXPAND_SZ:
GetRegesz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_MULTI_SZ:
GetRegmsz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_BINARY:
break;
default:
break;
}
}
}
//
// Get a REG_SZ value and stick it in the table entry, along with the
// length
//
BOOL GetRegsz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD *pdwLength)
{
BYTE achValue[1024];
DWORD dwLength;
LONG Status;
DWORD dwType = REG_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegGetValue( hKey,
NULL,
pszKey,
0x0000002, //RRF_RD_REG_SZ
&dwType,
(PVOID) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_SZ != dwType) )
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get the value of a REG_EXPAND_SZ and its length
//
BOOL GetRegesz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD * pdwLength)
{
BYTE achValue[1024];
DWORD dwLength;
LONG Status;
DWORD dwType = REG_EXPAND_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_EXPAND_SZ != dwType))
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get value and length of REG_MULTI_SZ
//
BOOL GetRegmsz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount( *pdwLength) PVOID * ppvValue, __out DWORD * pdwLength)
{
//BYTE achValue[1024];
BYTE achValue[2048]; // careful, some of these strings are quite long
DWORD dwLength;
LONG Status;
DWORD dwType = REG_MULTI_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_MULTI_SZ != dwType))
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get value and length of REG_DWORD
//
BOOL GetRegdw(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD * pdwLength)
{
DWORD dwValue = 0;
DWORD dwLength;
LONG Status;
DWORD dwType = REG_DWORD;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength) )
{
return FALSE;
}
dwLength = sizeof(dwValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &dwValue,
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_DWORD != dwType))
{
return FALSE;
}
*ppvValue = (PVOID) (ULONG_PTR) dwValue;
*pdwLength = dwLength;
return TRUE;
}
void
WriteRegistryKeyValues(
HKEY hCurrentKey,
DWORD NumberOfValues,
PREGENTRY pValues)
/*++
Routine Description:
This routine reads a bunch of values associated with a given key.
Arguments:
hCurrentKey - the key
NumberOfValues - the number of values
pValues - the array of values
Return Value:
None
--*/
{
DWORD i;
for (i = 0; i < NumberOfValues; i++)
{
DWORD dwType;
PVOID pvValue;
DWORD dwLength;
LPTSTR pszKey;
pszKey = pValues[i].pszKey;
dwType = pValues[i].dwType;
dwLength = pValues[i].dwLength;
pvValue = pValues[i].pvValue;
switch (dwType)
{
case REG_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_DWORD:
AddValue(hCurrentKey, pszKey, dwType, dwLength, &pvValue);
break;
case REG_EXPAND_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_MULTI_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_BINARY:
//
// There are no binary values we need to copy. If we did, we'd
// put something here
//
break;
default:
break;
}
}
}
//
// Open a key so we can read the values
//
BOOL OpenKey(
__in LPTSTR pszKey,
__out PHKEY phKey)
/*++
Routine Description:
This routine opens a registry key.
Arguments:
pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
phKey - the key handlle
Return Value:
TRUE if successful, otherwise FALSE
--*/
{
HKEY hNewKey = 0;
DWORD Status;
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
pszKey,
0,
KEY_QUERY_VALUE,
&hNewKey);
if (ERROR_SUCCESS != Status)
{
*phKey = NULL;
return FALSE;
}
else
{
*phKey = hNewKey;
return TRUE;
}
}
BOOL CreateKey(__in LPTSTR pszKey, __out PHKEY phKey)
/*++
Routine Description:
This routine creates a registry key.
Arguments:
pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
phKey - the key handlle
Return Value:
TRUE if successful, otherwise FALSE
--*/
{
LONG Status;
DWORD Disposition;
Status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
pszKey,
0,
REG_NONE,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
phKey,
&Disposition);
if ( ERROR_SUCCESS == Status)
{
return TRUE;
}
else
{
return FALSE;
}
}
//
// Add a value to the registry
//
BOOL AddValue(__in HKEY hKey, __in LPTSTR pszKey, __in DWORD dwType, __in DWORD dwLength, __in PVOID pvValue)
{
BOOL fSuccess = TRUE;
LONG Status = ERROR_SUCCESS;
Status = RegSetValueEx( hKey,
pszKey,
0,
dwType,
pvValue,
dwLength);
if (Status != ERROR_SUCCESS)
{
fSuccess = FALSE;
//RegCloseKey(hKey);
}
return fSuccess;
}

98
install/nfsreginst.h Normal file
View file

@ -0,0 +1,98 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
/*++
Copyright (c) 1997 - 1999 Microsoft Corporation
Module Name:
srfunc.h
Abstract:
--*/
#include <windows.h>
#include <stdlib.h>
#include <strsafe.h>
#include "nfs41_driver.h"
typedef struct {
LPTSTR pszKey;
DWORD dwType;
DWORD dwLength;
PVOID pvValue;
} REGENTRY, *PREGENTRY;
void
ReadRegistryKeyValues(
HKEY hKey,
DWORD Count,
PREGENTRY pValues);
void
WriteRegistryKeyValues(
HKEY hKey,
DWORD Count,
PREGENTRY pValues);
//
// routines for manipulating registry key values
//
BOOL GetRegsz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD *pdwLength);
BOOL GetRegesz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD * pdwLength);
BOOL GetRegmsz(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD * pdwLength);
BOOL GetRegdw(__in HKEY hKey, __in LPTSTR pszKey, __deref_out_bcount(*pdwLength) PVOID * ppvValue, __out DWORD * pdwLength);
//
// routines for manipulating registry keys
//
BOOL OpenKey(
__in LPTSTR pszKey,
__out PHKEY phKey);
BOOL CreateKey(__in LPTSTR pszKey, __out PHKEY phKey);
BOOL AddValue(__in HKEY hKey, __in LPTSTR pszKey, __in DWORD dwType, __in DWORD dwLength, __in PVOID pvValue);
BOOL RdrSetupProviderOrder( void );
BOOL RdrRemoveProviderFromOrder( void );
ULONG_PTR RdrGetProviderOrderString( __out LPTSTR *OrderString );
BOOL RdrSetProviderOrderString( __in LPTSTR OrderString );
typedef BOOL (*ACTIONVECTOR) ( void );
#define RDRSERVICE TEXT("nfs41_driver")
#define PROVIDER_NAME RDRSERVICE
#define PROVIDER_ORDER_KEY TEXT("System\\CurrentControlSet\\Control\\NetworkProvider\\Order")

15
install/sources Normal file
View file

@ -0,0 +1,15 @@
TARGETTYPE=PROGRAM
TARGETNAME=nfs_install
SOURCES=nfs_install.c nfsreginst.c
UMTYPE=console
USE_MSVCRT=1
INCLUDES=..\sys
!IF 0
/W3 is default level
bump to /Wall, but suppress warnings generated by system includes,
as well as the following warnings:
4100 - unused function call arguments (we have lots of stubs)
4127 - constant conditional (I like to use if(0) or if(1))
!ENDIF
MSC_WARNING_LEVEL=/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4100 /wd4127 /wd4201 /wd4214

46
libtirpc/.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
# files generated by autoconf, automake, autoheader and libtoolize
aclocal.m4
autom4te.cache
compile
config.guess
config.log
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
Makefile.in
missing
config.h.in
# files generated by configure
confdefs.h
config.status
conftest
conftest.c
conftest.cpp
conftest.er1
conftest.err
.deps
Makefile
config.h
stamp-h1
libtirpc.pc
# file generated during compilation
*.o
.libs
lib*.a
src/libtirpc.la
src/libtirpc_la-*.lo
# generic editor backup et al
*~
# cscope database files
cscope.*
# files generated by patches
*.patch
*.rej
*.orig
# files generated by debugging
.gdb_history
.gdbinit
core

3
libtirpc/AUTHORS Normal file
View file

@ -0,0 +1,3 @@
Gilles Quillard <gilles.quillard@bull.net>
Antoine Fraticelli <antoine.fraticelli@bull.net>

359
libtirpc/COPYING Normal file
View file

@ -0,0 +1,359 @@
Sun Industry Standards Source License 1.0
DEFINITIONS
1.1. "Commercial Use" means distribution or otherwise
making the Original Code available to a third party.
1.2. "Contributor Version" means the combination of the
Original Code, and the Modifications made by that particular
Contributor.
1.3. "Electronic Distribution Mechanism" means a mechanism
generally accepted in the software development community for
the electronic transfer of data.
1.4. "Executable" means Original Code in any form other
than Source Code.
1.5. "Initial Developer" means the individual or entity
identified as the Initial Developer in the Source Code
notice required by 2 (Exhibit A)
1.6. "Larger Work" means a work which combines Original
Code or portions thereof with code not governed by the terms
of this License.
1.7. "License" means this document.
1.8. "Licensable" means having the right to grant, to the
maximum extent possible, whether at the time of the initial
grant or subsequently acquired, any and all of the rights
conveyed herein.
1.9. "Modifications" means any addition to or deletion from
the substance or structure of either the Original Code or
any previous Modifications. A Modification is:
A. Any addition to or deletion from the contents of a file
containing Original Code or previous Modifications.
B. Any new file that contains any part of the Original Code
or previous Modifications. .
1.10. "Original Code" means Source Code of computer
software code which is described in the Source Code notice
required by Exhibit A as Original Code.
1.11. "Patent Claims" means any patent claims, now owned or
hereafter acquired, including without limitation, method,
process, and apparatus claims, in any patent Licensable by
grantor.
1.12. "Source Code" means the preferred form of the
Original Code for making modifications to it, including all
modules it contains, plus any associated interface
definition files, or scripts used to control compilation and
installation of an Executable.
1.13. "Standards" means the standard identified in Exhibit
B or a subsequent version of such standard.
1.14. "You" or "Your" means an individual or a legal entity
exercising rights under, and complying with all of the terms
of, this License or a future version of this License issued
under Section 6.1. For legal entities, "You" includes any
entity which controls, is controlled by, or is under common
control with You. For purposes of this definition,
"control" means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by
contract or otherwise, or (b) ownership of more than fifty
percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2.0 SOURCE CODE LICENSE
2.1 The Initial Developer Grant: The Initial Developer
hereby grants You a world-wide, royalty-free, non-exclusive
license, subject to third party intellectual property
claims:
a) under intellectual property rights (other than patent or
trademark) Licensable by Initial Developer to use,
reproduce, modify, display, perform, sub license and
distribute the Original Code (or portions thereof )with or
without Modifications, and/or as part of a Larger Work; and
b) under Patents Claims infringed by the making, using or
selling of Original Code, to make, have made, use, practice,
sell, and offer for sale, and/or otherwise dispose of the
Original Code (or portions thereof).
c) the licenses granted in this Section 2.1(a ) and (b) are
effective on the date Initial Developer first distributes
Original Code under the terms of this License.
d) Notwithstanding Section 2.1(b )above, no patent license
is granted: 1) for code that You delete from the Original
Code; 2) separate from the Original Code; or 3) for
infringements caused by: i) the modification of the
Original Code or
ii) the combination of the Original Code with other software
or devices, including but not limited to Modifications.
3.0 DISTRIBUTION OBLIGATIONS
3.1 Application of License. The Source Code version of
Original Code may be distributed only under the terms of
this License or a future version of this License released
under Section 6.1, and You must include a copy of this
License with every copy of the Source Code You distribute.
You may not offer or impose any terms on any Source Code
version that alters or restricts the applicable version of
this License or the recipient's rights hereunder. Your
license for shipment of the Contributor Version is
conditioned upon your full compliance with this Section.
The Modifications which you create must comply with all
requirements set out by the Standards body in effect 120
days before You ship the Contributor Version. In the event
that the Modifications do not meet such requirements, You
agree to publish (i) any deviation from the Standards
protocol resulting from implementation of your Modifications
and (ii) a reference implementation of Your Modifications,
and to make any such deviation and reference implementation
available to all third parties under the same terms as the
license on a royalty free basis within thirty (30) days of
Your first customer shipment of Your Modifications.
3.2 Required Notices. You must duplicate the notice in
Exhibit A in each file of the Source Code. If it is not
possible to put such notice in a particular Source Code file
due to its structure, then You must include such notice in a
location (such as a relevant directory ) where a user would
be likely to look for such a notice. If You created one or
more Modifications ) You may add your name as a Contributor
to the notice described in Exhibit A. You must also
duplicate this License in any documentation for the Source
Code where You describe recipients' rights or ownership
rights relating to Initial Code. You may choose to offer,
and to charge a fee for, warranty, support, indemnity or
liability obligations to one or more recipients of Your
version of the Code. However, You may do so only
on Your own behalf, and not on behalf of the Initial
Developer. You must make it absolutely clear than any such
warranty, support, indemnity or liability obligation is
offered by You alone, and You hereby agree to indemnify the
Initial Developer for any liability incurred by the Initial
Developer as a result of warranty, support, indemnity or
liability terms You offer.
3.3 Distribution of Executable Versions. You may distribute
Original Code in Executable and Source form only if the
requirements of Section 3.1 and 3.2 have been met for that
Original Code, and if You include a notice stating that the
Source Code version of the Original Code is available under
the terms of this License. The notice must be conspicuously
included in any notice in an Executable or Source versions,
related documentation or collateral in which You describe
recipients' rights relating to the Original Code. You may
distribute the Executable and Source versions of Your
version of the Code or ownership rights under a license of
Your choice, which may contain terms different from this
License, provided that You are in compliance with the terms
of this License. If You distribute the Executable and
Source versions under a different license You must make it
absolutely clear that any terms which differ from this
License are offered by You alone, not by the Initial
Developer . You hereby agree to indemnify the Initial
Developer for any liability incurred by the Initial
Developer as a result of any such terms You offer .
3.4 Larger Works. You may create a Larger Work by combining
Original Code with other code not governed by the terms of
this License and distribute the Larger Work as a single
product. In such a case, You must make sure the
requirements of this License are fulfilled for the Original
Code.
4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION
If it is impossible for You to comply with any of the terms
of this License with respect to some or all of the Original
Code due to statute, judicial order, or regulation then You
must:
a) comply with the terms of this License to the maximum
extent possible; and
b) describe the limitations and the code they affect. Such
description must be included in the LEGAL file described in
Section 3.2 and must be included with all distributions of
the Source Code. Except to the extent prohibited by statute
or regulation, such description must be sufficiently
detailed for a recipient of ordinary skill to be able to
understand it.
5.0 APPLICATION OF THIS LICENSE This License applies to code
to which the Initial Developer has attached the notice in
Exhibit A and to related Modifications as set out in Section
3.1.
6.0 VERSIONS OF THE LICENSE
6.1 New Versions. Sun Microsystems, Inc. Sun may publish
revised and/or new versions of the License from time to
time. Each version will be given a distinguishing version
number .
6.2 Effect of New Versions. Once Original Code has been
published under a particular version of the License, You may
always continue to use it under the terms of that version.
You may also choose to use such Original Code under the
terms of any subsequent version of the License published by
Sun. No one other than Sun has the right to modify the
terms applicable to Original Code.
7. DISCLAIMER OF W ARRANTY. ORIGINAL CODE IS PROVIDED
UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY
ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
INITIAL DEVELOPER )ASSUME THE COST OF ANY NECESSARY
SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO
USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT
UNDER THIS DISCLAIMER.
8.0 TERMINATION
8.1 This License and the rights granted hereunder will
terminate automatically if You fail to comply with terms
herein and fail to cure such breach within 30 days of
becoming aware of the breach. All sublicenses to the
Original Code which are properly granted shall survive any
termination of this License. Provisions which, by their
nature, must remain in effect beyond the termination of this
License shall survive.
8.2 .In the event of termination under Section 8.1 above,
all end user license agreements (excluding distributors and
resellers) which have been validly granted by You or any
distributor hereunder prior to termination shall survive
termination.
9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO
LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE) ,CONTRACT,
OR OTHER WISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER
CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY
SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
LOSS OF GOOD WILL, WORK STOPPAGE, COMPUTER FAILURE OR
MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT
APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME
JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND
LIMITATION MAY NOT APPLY TO YOU.
10.0 U .S. GOVERNMENT END USERS U.S. Government: If this
Software is being acquired by or on behalf of the U.S.
Government or by a U.S. Government prime contractor or
subcontractor (at any tier), then the Government's rights in
the Software and accompanying documentation shall be only as
set forth in this license; this is in accordance with 48 C.F
.R. 227.7201 through 227.7202-4 (for Department of Defense
(DoD) acquisitions )and with 48 C.F.R.2.101 and 12.212( for
non-DoD acquisitions).
11.0 MISCELLANEOUS This License represents the complete
agreement concerning subject matter hereof. If any
provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to
make it enforceable. This License shall be governed by
California law provisions (except to the extent applicable
law, if any, provides otherwise), excluding its
conflict-of-law provisions. With respect to disputes in
which at least one party is a citizen of, or an entity
chartered or registered to do business in the United States
of America, any litigation relating to this License shall be
subject to the jurisdiction of the Federal Courts of the
Northern District of California, with venue lying in Santa
Clara County, California, with the losing party responsible
for costs, including without limitation, court costs and
reasonable attorneys fees and expenses. The application of
the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any law
or regulation which provides that the language of a contract
shall be construed against the drafter shall not apply to
this License.
EXHIBIT A - Sun Standards
"The contents of this file are subject to the Sun Standards
License Version 1.0 the (the "License";) You may not use
this file except in compliance with the License. You may
obtain a copy of the License at
_______________________________.
Software distributed under the License is distributed on
an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
express or implied. See the License for the specific
language governing rights and limitations under the License.
The Original Code is Copyright 1998 by Sun Microsystems, Inc
The Initial Developer of the Original Code is: Sun
Microsystems, Inc.
Portions created by _____________________________ are
Copyright ______________________________.
All Rights Reserved.
Contributors: ______________________________________.
EXHIBIT B - Sun Standards
The Standard is defined as the following IETF RFCs:
RFC1831: RPC: Remote Procedure Call Protocol Specification
Version 2 RFC1832: XDR: External Data REpresentation
Standard RFC1833: Binding Protocols for ONC RPC Version 2
RFC2078: Generic Security Service Application Program
Interface, Version 2 RFC2203: RPCSEC_GSS Protocol
Specification RFC2695: Authentication Mechanisms for ONC RPC
*
* Copyright (c) Copyright (c) Bull S.A. 2005 All Rights Reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

206
libtirpc/ChangeLog Normal file
View file

@ -0,0 +1,206 @@
2008-11-19 Steve Dickson <steved@redhat.com>
* Version 0.1.10 released.
commit 32ec5931e3debf208972d5146578f08dc113a9b6
Merge: 338af7f... 92cf0dd...
Author: Steve Dickson <steved@redhat.com>
Date: Mon Nov 17 12:26:22 2008 -0500
Merge branch 'master' of git://git.infradead.org/~steved/libtirpc
commit 92cf0dde310ca341a2f29ff66b19eeb9994a649a
Author: Ian Kent <ikent@redhat.com>
Date: Tue Oct 28 11:19:07 2008 -0400
Fixed a warings the IPV6 client routines
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 338af7f9f00e096b65a6d823f885c4eeaf1d1f8c
Author: Steve Dickson <steved@redhat.com>
Date: Mon Oct 27 12:46:54 2008 -0400
__rpc_taddr2uaddr_af() assumes the netbuf to always have a
non-zero data. This is a bad assumption and can lead to a
seg-fault. This patch adds a check for zero length and returns
NULL when found.
Signed-off-by: Steve Dickson <steved@redhat.com>
commit d9a5ae7079d001a9e3b9b384f9153f591a7158bd
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:10:43 2008 -0400
Fix __rpc_getconfip
__rpc_getconfip is supposed to return the first netconf
entry supporting tcp or udp, respectively. The code will
currently return the *last* entry, plus it will leak
memory when there is more than one such entry.
This patch fixes this issue.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 6c487efe74adb5c29f7bee5bd51b3ebef4968f7d
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:09:06 2008 -0400
Fix getpeereid
getpeereid fails because it uses an incorrect getsockopt call to obtain
the peer credentials on a AF_LOCAL socket. This in turn will cause all
RPC services to be registered with rpcbind to show up as having been
registered by "unknown".
This has a serious impact on security - a service owned by "unknown"
can essentially be unregistered (and thus replaced) by anyone.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 851b0f5c6dca22d634603f03f0a5e3e35c6db867
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:08:07 2008 -0400
svc_getcaller_netbuf macro seems broken
I haven't found any documentation, but the comment in the header
file seems to suggest that svc_getcaller_netbuf should return the
xp_rtaddr netbuf. Returning the address of the socket descripor
seems to be wrong at any rate.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit d94b92d5125242ce595c1baf42a1e6d1004b7756
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:06:54 2008 -0400
Introduce __rpc_set_netbuf helper
The RPC code contains a number of places where a netbuf
is initialized with some data. All the mem_alloc/memcpy
stuff is open-coded. Introduce a helper function and
convert the code.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit da5f9861ea3bae59c8eead26d38334721caa9f0a
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:05:20 2008 -0400
Kill map_ipv4_to_ipv6
After the change to svc_vc.c performed in the previous patch,
this function is no longer needed.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 59c374c4b507aeca957ed0096d98006edf601375
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:04:17 2008 -0400
Fix xp_raddr handling in svc_fd_create etc
Currently svc_fd_create tries to do some clever tricks
with IPv4/v6 address mapping.
This is broken for several reasons.
1. We don't want IPv4 based transport to look like IPv6
transports. Old applications compiled against tirpc
will expect AF_INET addresses, and are not equipped
to deal with AF_INET6.
2. There's a buffer overflow.
memcpy(&sin6, &ss, sizeof(ss));
copies a full struct sockaddr to a sockaddr_in6 on
the stack. Unlikely to be exploitable, but I wonder
if this ever worked....
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 628788c1cc84c86ee4cb36ee5d4fe8954e90fca5
Author: Steve Dickson <steved@redhat.com>
Date: Tue Sep 16 11:32:31 2008 -0400
- Fixed version-info in src/Makefile.am to reflect the correct version
- Fixed some of warnings in: src/auth_time.c, src/clnt_dg.c and
src/clnt_raw.c
- Added some #ifdef NOTUSED around some code in src/rpbc_clnt.c
that was not being used...
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 9e7ba0c7a02031294fefadfbca42b3dd5f2d841f
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 16 08:46:29 2008 -0400
Fix for taddr2addr conversion bug of local addresses
When converting af_local socket addresses in taddr2uaddr, an incorrect
sizeof() would result in a truncated path string. As a result,
rpcbind will report the local /var/lib/rpcbind address to clients
as "/v" on a 32bit machine.
Signed-off-by: okir@suse.de
Signed-off-by: Steve Dickson <steved@redhat.com>
commit ea9f048761d0b9a2ab6310bffa07351f0b04d8c5
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 2 12:11:15 2008 -0400
Always make IPv6 sockets V6ONLY
Assume you have a netconfig file looking like this:
udp tpi_clts v inet udp - -
udp6 tpi_clts v inet6 udp - -
...
a call to svc_tli_create(... &someaddr, "udp") will fail to create an
IPv6 server socket. The problem is that on Linux, passive IPv6 sockets
will also accept packets/connections from IPv4, and will simply map
the sender's address to an IPv6 mapped IPv4 address. So if you want to
bind both a UDPv4 and UDPv6 socket to the same port, this will fail with
EADDRINUSE.
The way to avoid this behavior is to change the socket to V6ONLY,
which tells the kernel to avoid the autmatic mapping.
The change proposed in the patch below does this. I *think* this is
a good place to do this, as it will also fix applications that do not
use svc_tli_create() - such as rpcbind, which creates the sockets on
its own using __rpc_nconf2fd.
I think this also improves portability, as BSD code assumes BSD
behavior, where this mapping does not occur either.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 95c8f7227e6b15f2e430d7b87dadc95b2acd4a61
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 2 12:09:39 2008 -0400
Fix incorrect sizeof() in __rpc_getbroadifs
__rpc_getbroadifs returns bad broadcast addresses on 32bit
machines because when copying the broadcast addresses, ite
applies the sizeof() operator to a pointer to a sockaddr,
rather than the sockaddr itself.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
2004-10-13 Antoine Fraticelli <antoine.fraticellie@bull.net>
* Version 0.1 released.
2005-01-07 Gilles Quillard <Gilles.Quillard@bull.net>
* Version 0.1.5 Fix problems links to the use of Kerberos.

251
libtirpc/INSTALL Normal file
View file

@ -0,0 +1,251 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
TI-RPC Library Quick Installation
=================================
Without GSS API
$ ./configure
$ make
# make install
To enable utilization of RPCSEC via GSS API use following commands
but you need to install libgssapi from the CITI before
$ ./configure --enable-gss
$ make
# make install
Once installed, you can customize the /etc/netconfig configuration file
to configure the supported protocols. To support INET6 udp/tcp, uncomment
the udp6/tcp6 lines.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

36
libtirpc/Makefile.am Normal file
View file

@ -0,0 +1,36 @@
SUBDIRS = src man doc
nobase_include_HEADERS = tirpc/netconfig.h \
tirpc/rpcsvc/crypt.x \
tirpc/rpcsvc/crypt.h \
tirpc/rpc/xdr.h \
tirpc/rpc/types.h \
tirpc/rpc/svc_soc.h \
tirpc/rpc/svc.h \
tirpc/rpc/svc_dg.h \
tirpc/rpc/svc_auth.h \
tirpc/rpc/rpc_msg.h \
tirpc/rpc/rpc.h \
tirpc/rpc/rpcent.h \
tirpc/rpc/rpc_com.h \
tirpc/rpc/rpcb_prot.x \
tirpc/rpc/rpcb_prot.h \
tirpc/rpc/rpcb_clnt.h \
tirpc/rpc/raw.h \
tirpc/rpc/pmap_rmt.h \
tirpc/rpc/pmap_prot.h \
tirpc/rpc/pmap_clnt.h \
tirpc/rpc/nettype.h \
tirpc/rpc/des.h \
tirpc/rpc/des_crypt.h \
tirpc/rpc/clnt_stat.h \
tirpc/rpc/clnt_soc.h \
tirpc/rpc/clnt.h \
tirpc/rpc/auth_unix.h \
tirpc/rpc/auth_kerb.h \
tirpc/rpc/auth.h \
tirpc/rpc/auth_gss.h \
tirpc/rpc/auth_des.h
pkgconfigdir=$(libdir)/pkgconfig
pkgconfig_DATA = libtirpc.pc

3
libtirpc/NEWS Normal file
View file

@ -0,0 +1,3 @@
New in 0.1:
* Portage from FreeBSD 5.2.1 (security part to be completed)
* Use autoconf/automake

44
libtirpc/README Normal file
View file

@ -0,0 +1,44 @@
LIBTIRPC 0.1 FROM SUN'S TIRPCSRC 2.3 29 Aug 1994
This package contains SunLib's implementation of transport-independent
RPC (TI-RPC) documentation. This library forms a piece of the base of Open Network
Computing (ONC), and is derived directly from the Solaris 2.3 source.
TI-RPC is an enhanced version of TS-RPC that requires the UNIX System V
Transport Layer Interface (TLI) or an equivalent X/Open Transport Interface
(XTI). TI-RPC is on-the-wire compatible with the TS-RPC, which is supported
by almost 70 vendors on all major operating systems. TS-RPC source code
(RPCSRC 4.0) remains available from several internet sites.
This release was a native source release, compatible for
building on Solaris 2.3. It had been ported from FreeBSD 5.2.1 to GNU/Linux
in 2004.
Applications linked with this release's librpc must link with the United
States domestic version of libcrypt in order to resolve the cbc_crypt() and
ecb_crypt() functions. These routines are used with Secure RPC however all
RPC programs that link with this release's librpc will need to link with the
domestic libcrypt.
WHAT'S NEW IN THIS RELEASE: TIRPCSRC 2.3 FROM SUN
The previous release was TIRPCSRC 2.0.
1. This release is based on Solaris 2.3. The previous release was
based on Solaris 2.0. This release contains a siginificant number of
bug fixes and other enhancements over TIRPCSRC 2.0.
2. The RPC library is thread safe for all client-side interfaces
(clnt_create, clnt_call, etc.). The server-side interfaces
(svc_create, svc_run, etc.) are not thread safe in this release. The
server-side interfaces will be made thread safe in the next release of
TIRPCSRC. Please see the manual pages for details about which
interfaces are thread safe.
3. As part of the work to make the RPC library thread-safe, rpcgen has
been enhanced to generate thread-safe RPC stubs (the -M option). Note
that this modifies the call-signature for the stub functions; the
procedure calling the RPC stub must now pass to the stub a pointer to
an allocated structure where results will be placed by the stub. See
the rpcgen manual page and the rpcgen Programming Guide for details.

6
libtirpc/THANKS Normal file
View file

@ -0,0 +1,6 @@
Thanks to for
Aurelien Charbon <aurelien.charbon@bull.net> TI-RPC portage from NetBSD
BSD Communauty TI-RPC improvement from Sun implementation

3
libtirpc/TODO Normal file
View file

@ -0,0 +1,3 @@
* Support of DES & other security part
* Provide tests
* rpcgen command missing

7
libtirpc/VERSION Normal file
View file

@ -0,0 +1,7 @@
# This file is used by configure to get version information
#
PKG_MAJOR=0
PKG_MINOR=1
PKG_REVISION=11
PKG_BUILD=0

42
libtirpc/autogen.sh Normal file
View file

@ -0,0 +1,42 @@
#!/bin/sh -e
echo -n cleaning up .
# Clean up the generated crud
(
for FILE in compile config.guess config.sub depcomp install-sh ltmain.sh missing mkinstalldirs; do
if test -f $FILE; then
rm -f $FILE
fi
echo -n .
done
)
for FILE in aclocal.m4 configure config.h.in; do
if test -f $FILE; then
rm -f $FILE
fi
echo -n .
done
for DIR in autom4te.cache; do
if test -d $DIR; then
rm -rf $DIR
fi
echo -n .
done
find . -type f -name 'Makefile.in' -print0 | xargs -r0 rm -f --
find . -type f -name 'Makefile' -print0 | xargs -r0 rm -f --
echo ' done'
if test x"${1}" = x"clean"; then
exit
fi
aclocal
libtoolize --force --copy
autoheader
automake --add-missing --copy --gnu # -Wall
autoconf # -Wall

10
libtirpc/bootstrap Normal file
View file

@ -0,0 +1,10 @@
[ -e Makefile ] && make clean
rm -rf autom4te.cache configure Makefile stamp-h1
rm -rf src/Makefile src/.deps
rm -rf Makefile.in aclocal.m4 config.log config.h
rm -rf depcomp missing install-sh config.status
aclocal
autoheader
automake --gnu --add-missing -c
autoconf
rm -rf autom4te.cache config.log libtool stamp-h1*

29
libtirpc/configure.ac Normal file
View file

@ -0,0 +1,29 @@
AC_INIT(libtirpc, 0.2.1)
AM_INIT_AUTOMAKE(libtirpc, 0.2.1)
AM_MAINTAINER_MODE
AC_CONFIG_SRCDIR([src/auth_des.c])
AC_ARG_ENABLE(gss,[ --enable-gss Turn on gss api], [case "${enableval}" in
yes) gss=true ; AC_CHECK_LIB([gssapi],[gss_init_sec_context]) ;;
no) gss=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gss) ;;
esac],[gss=false])
AM_CONDITIONAL(GSS, test x$gss = xtrue)
if test x$gss = xtrue; then
AC_DEFINE(HAVE_LIBGSSAPI, 1, [])
PKG_CHECK_MODULES(GSSGLUE, libgssglue, [],
AC_MSG_ERROR([Unable to locate information required to use libgssglue.]))
fi
AC_PROG_CC
AM_CONFIG_HEADER(config.h)
AC_PROG_LIBTOOL
##AC_PROG_RANLIB
AC_HEADER_DIRENT
AC_PREFIX_DEFAULT(/usr)
AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h locale.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h])
AC_CHECK_LIB([pthread], [pthread_create])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile])
AC_OUTPUT(libtirpc.pc)

Some files were not shown because too many files have changed in this diff Show more