From 8fdcc9408c419ee2e250a7c0920b43be1ea61809 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 5 Nov 2004 19:21:32 +0000 Subject: [PATCH] STABLE14-windows-pullup-20041105 Pullup of all changes since the 1.3.72/73 release --- README-NT | 319 ++-- doc/txt/winnotes/afs-changes-since-1.2.txt | 28 + doc/txt/winnotes/afs-install-notes.txt | 49 +- doc/txt/winnotes/afs-issues.txt | 54 +- doc/txt/winnotes/registry.txt | 23 +- src/WINNT/afsapplib/NTMakefile | 3 + src/WINNT/afsd/NTMakefile | 18 +- src/WINNT/afsd/afsd.c | 1 + src/WINNT/afsd/afsd95.c | 1 + src/WINNT/afsd/afsd_init.c | 3 +- src/WINNT/afsd/afsd_service.c | 9 +- src/WINNT/afsd/afskfw.c | 63 +- src/WINNT/afsd/cm.h | 9 +- src/WINNT/afsd/cm_buf.c | 35 +- src/WINNT/afsd/cm_buf.h | 2 + src/WINNT/afsd/cm_conn.c | 42 +- src/WINNT/afsd/cm_freelance.c | 307 +++- src/WINNT/afsd/cm_freelance.h | 10 +- src/WINNT/afsd/cm_ioctl.c | 55 +- src/WINNT/afsd/cm_scache.c | 1362 ++++++++--------- src/WINNT/afsd/cm_scache.h | 12 +- src/WINNT/afsd/cm_vnodeops.c | 61 +- src/WINNT/afsd/cm_vnodeops.h | 1 + src/WINNT/afsd/smb.c | 107 +- src/WINNT/afsd/smb3.c | 43 +- src/WINNT/afsd/symlink.c | 7 +- src/WINNT/afssvrcfg/NTMakefile | 3 + src/WINNT/afssvrcpa/NTMakefile | 4 +- src/WINNT/afssvrmgr/NTMakefile | 7 +- src/WINNT/afsusrmgr/NTMakefile | 5 + src/WINNT/client_config/config.cpp | 96 +- src/WINNT/client_creds/NTMakefile | 5 + .../client_exp/lang/en_US/afs_shl_ext.rc | 16 +- .../client_exp/make_symbolic_link_dlg.cpp | 2 +- src/WINNT/install/wix/NTMakefile | 3 +- src/WINNT/install/wix/config.wxi | 15 + src/WINNT/install/wix/feature.wxi | 39 +- src/WINNT/install/wix/files.wxi | 44 +- src/WINNT/install/wix/openafs.wxs | 2 +- src/WINNT/pthread/pthread.c | 20 +- src/sys/pioctl_nt.c | 2 +- 41 files changed, 1718 insertions(+), 1169 deletions(-) diff --git a/README-NT b/README-NT index 292aa72ad..40e4103fb 100644 --- a/README-NT +++ b/README-NT @@ -42,17 +42,38 @@ The Microsoft development tools require anywhere from 660 MB to 1.8GB of storage depending on which compilers are selected. The following versions are supported: - Microsoft Visual C++ 6.0 Microsoft Visual .NET + available via a MSDN subscription + Microsoft Visual .NET 2003 (recommended) + available via a MSDN subscription + + Microsoft Visual C++ Toolkit 2003 (same as .NET 2003) + http://msdn.microsoft.com/visualc/vctoolkit2003/ + +The following Microsoft SDK is required: + + Microsoft Platform SDK for Windows XP SP2 [Core, Data Access and Installer SDKs are required] + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/downlevel.htm [IE required] + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm + +The following Microsoft DDK is required: - Microsoft Platform SDK for Windows XP SP2 - [Core and Data Access SDKs are required] + Microsoft Windows Server 2003 DDK + available via a MSDN subscription or via free CD + http://www.microsoft.com/whdc/devtools/ddk/orderddkcd.mspx The NSIS installer requires about 14 MB of storage. The following -version is supported. +version is supported: Nullsoft Scriptable Installation System 2.0 + http://nsis.sourceforge.net/home/ + +The WiX installer requires about 18 MB of storage. The following +version is supported: + + Wix 2.0.2217.0 + http://prdownloads.sourceforge.net/wix/sources-2.0.2217.0.zip The InstallShield scripts (although not supported) require version 5.5 of InstallShiled. Version 6.0 or higher of InstallShield are not @@ -69,13 +90,13 @@ Transfer OpenAFS source tree onto your hardrive. The source can be downloaded from the OpenAFS web site: http://www.OpenAFS.org/release/snapindex.html. -For this example, download source for version 1.3.60 using the +For this example, download source for version 1.3.74 using the following URL: -http://www.openafs.org/dl/openafs/1.3.60/openafs-1.3.60-src.tar +http://www.openafs.org/dl/openafs/1.3.74/openafs-1.3.74-src.tar HINT: DailySnapShots are pre-release source trees and much more likely to have compilation errors. If this is your first attempt, do -your build based on a release version of the source, e.g. 1.3.60. Once +your build based on a release version of the source, e.g. 1.3.74. Once you have completed a build process successfully, you can experiment with other source trees. @@ -83,23 +104,24 @@ You will need an unzip utility that can expand compressed tar files. For example "Pkzip for Windows" from Pkware will uncompress tar files. (http://www.pkware.com/) -Expand the downloaded tar file (openafs-1.3.60-src.tar) into target +Expand the downloaded tar file (openafs-1.3.74-src.tar) into target directory (c:\OpenAFS), the unzip routine will expand the source into a subdirectory tree: - c:\OpenAFS\OpenAFS-1.3.60\src + c:\OpenAFS\OpenAFS-1.3.74\src Copy the files 'NTMakefile' and 'ntbuild.bat' from 'src' to the OpenAFS -base directory: +base directory (aka %AFSROOT%): From a DOS command prompt window, enter the following copy commands: - copy c:\OpenAFS\OpenAFS-1.3.60\src\NTMakefile c:\OpenAFS\OpenAFS-1.3.60\. - copy c:\OpenAFS\OpenAFS-1.3.60\src\ntbuild.bat c:\OpenAFS\OpenAFS-1.3.60\. + cd c:\OpenAFS\OpenAFS-1.3.74 + copy src\NTMakefile . + copy src\ntbuild.bat . The AFS base directory should look something like the following: - c:\OpenAFS\OpenAFS-1.3.60\ + c:\OpenAFS\OpenAFS-1.3.74\ NTMakefile ntbuild.bat src @@ -107,8 +129,8 @@ The AFS base directory should look something like the following: STEP B. Install compiler and development tools. -Install a copy of Microsoft Visual C++ 6.0, Visual .NET, or Visual .NET 2003. -The "Typical" install setting is sufficient. +Install a copy of Microsoft Visual .NET, Visual .NET 2003, Visual C++ +Toolkit 2003. The "Typical" install setting is sufficient. (1) You can reduce the installation size by selecting "Custom" install and remove all but the following Options: @@ -121,17 +143,19 @@ and remove all but the following Options: STEP C. Install SDK header files. -Files from Microsoft's Platform SDK (August 2001 or later) are required to -complete a build on Windows 2000 or XP. You can install the "Core SDK" -from +Files from Microsoft's Platform SDK for Windows XP SP2 is required to +complete a build on Windows 2000/XP/2003. You can install the "Core, Data +Access and Installer SDKs" from http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ by using Internet Explorer 5.x or higher. (Active X controls are required) +If you do not which to use IE a complete SDK package is available from + + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm The header files that are required are found from a Microsoft SDK are: - netspi.h (Windows 9x builds) npapi.h (Windows 2000,XP,2003 builds) netcfgx.h (NSIS Loopback Adapter installer - Windows 2000,XP,2003 builds) netcfgn.h (NSIS Loopback Adapter installer - Windows 2000,XP,2003 builds) @@ -139,16 +163,11 @@ The header files that are required are found from a Microsoft SDK are: These files come from the following Microsoft DDKs/SDKs: npapi.h: - Windows XP/2003 Platform SDK - include/ + Windows XP SP2 Platform SDK - include/ netcfgn.h, netcfgx.h: Windows XP/2003 DDK - inc/wxp/ - netmpr.h, netspi.h: - July 1998 Windows 95 DDK - net/inc/netmpr.h and net/inc/netspi.h - July 1999 Windows 98 DDK - src/net/inc/netmpr.h and src/net/inc/netspi.h - - you need to install "Legacy and Related - driver samples" STEP D. Configure NTBUILD.BAT. @@ -159,6 +178,7 @@ must be defined to match your configuration: AFSVER_CL: Set to 1200 if using MS Visual C++ 6.0 Set to 1300 if using MS Visual .NET Set to 1310 if using MS Visual .NET 2003 + Set to 1400 if using MS Visual .NET 2005 MSVCDIR: Set to the short name version of the directory into which the visual C++ compiler was installed regardless of version @@ -184,17 +204,17 @@ Edit file %AFSROOT%\src\config\NTMakefile.i386_nt40 AFSPRODUCT_VER_MINOR - Version Minor Number AFSPRODUCT_VER_PATCH - Version Patch Number AFSPRODUCT_VER_BUILD - Version Build Number - CELLSERVDB_INSTALL - The default file name for the CellServDB - included in the install Package. - CELLNAME_DEFAULT - The default home cell name. - CELLSERVDB_WEB - The default web address to obtain CellServDB + CELLSERVDB_INSTALL - The default file name for the CellServDB + included in the install Package. + CELLNAME_DEFAULT - The default home cell name. + CELLSERVDB_WEB - The default web address to obtain CellServDB For example: in the file %AFSROOT%\src\config\NTMakefile.i386_nt40 you would see the following: AFSPRODUCT_VER_MAJOR=1 AFSPRODUCT_VER_MINOR=3 - AFSPRODUCT_VER_PATCH=6000 + AFSPRODUCT_VER_PATCH=7400 AFSPRODUCT_VER_BUILD=0 CELLNAME_DEFAULT=openafs.org CELLSERVDB_INSTALL=CellServDB.GrandCentral @@ -206,7 +226,7 @@ one that can be downloaded from the web (CELLSERVDB_WEB). STEP F. Begin the build -(1) From Windows 2000/XP open up a DOS prompt window. +(1) From Windows 2000/XP/2003 open up a DOS prompt window. (2) Change to the %AFSROOT% directory @@ -267,16 +287,16 @@ sources. The following changes were made to exehead\config.h. STEP H. Build OpenAFS NSIS install package -From the DOS command prompt window run: +From the %AFSROOT% directory execute: nmake /f NTMakefile NSIS STEP I. Install Wix MSI Installer -Download the Wix 2.0.1927.1 installer from +Download the Wix 2.0.2217.0 installer from - http://prdownloads.sourceforge.net/wix/sources-2.0.1927.1.zip + http://prdownloads.sourceforge.net/wix/sources-2.0.2217.0.zip Apply the following patches to the source tree and execute @@ -284,152 +304,114 @@ Apply the following patches to the source tree and execute from the \src\wix directory. +Index: src/wix/Common.cs +=================================================================== +RCS file: /cvsroot/wix/wix/src/wix/Common.cs,v +retrieving revision 1.7 +diff -w -r1.7 Common.cs +140a141,146 +> public static long GetFileTimeFromDateTime(string dateTime) +> { +> System.DateTime sdt = System.Xml.XmlConvert.ToDateTime(dateTime); +> return sdt.ToFileTime(); +> } +> Index: src/wix/Compiler.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Compiler.cs,v -retrieving revision 1.10 -diff -u -w -r1.10 Compiler.cs ---- src/wix/Compiler.cs 28 Jul 2004 15:50:22 -0000 1.10 -+++ src/wix/Compiler.cs 4 Aug 2004 16:28:16 -0000 -@@ -647,7 +647,7 @@ - // add the core registry keys for each context in the class - for (int i = 0; i < contextCount; ++i) - { -- this.AddRegistryKey(sourceLineNumbers, null, 0, String.Concat("CLSID\\", classId, "\\", context[i]), String.Empty, String.Concat("\"[!", fileServer, "]", argument == null ? String.Empty : " ", argument, "\""), componentId); // ClassId context -+ this.AddRegistryKey(sourceLineNumbers, null, 0, String.Concat("CLSID\\", classId, "\\", context[i]), String.Empty, String.Concat("\"[#", fileServer, "]", argument == null ? String.Empty : " ", argument, "\""), componentId); // ClassId context - if (null != icon) // ClassId default icon - { - if (null != iconIndex) -@@ -7385,6 +7385,20 @@ - break; - } - break; -+ case "Delete": -+ switch (attrib.Value) -+ { -+ case "install": -+ events |= MsiInterop.MsidbServiceControlEventDelete; -+ break; -+ case "uninstall": -+ events |= MsiInterop.MsidbServiceControlEventUninstallDelete; -+ break; -+ case "both": -+ events |= MsiInterop.MsidbServiceControlEventDelete | MsiInterop.MsidbServiceControlEventUninstallDelete; -+ break; -+ } -+ break; - case "Wait": - wait = Common.IsYes(attrib.Value, sourceLineNumbers, node.Name, attrib.Name, id) ? "1" : "0"; // strings used since integer column is nullable - break; -@@ -8715,6 +8729,7 @@ - } - bits ^= (bit * 65536); - break; -+ - default: - bit = this.NameToBit(MsiInterop.CommonControlAttributes, attrib.Name, attrib.Value, node.Name, id); - if (-1 == bit) +retrieving revision 1.14 +diff -w -r1.14 Compiler.cs +847c847 +< this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", context[i]), String.Empty, String.Concat("\"[!", fileServer, "]", argument == null ? String.Empty : " ", argument, "\""), componentId); // ClassId context +--- +> this.AddRegistryKey(sourceLineNumbers, null, MsiInterop.MsidbRegistryRootClassesRoot, String.Concat("CLSID\\", classId, "\\", context[i]), String.Empty, String.Concat("\"[#", fileServer, "]", argument == null ? String.Empty : " ", argument, "\""), componentId); // ClassId context +2352a2353,2358 +> // if a Value attribute was given by itself, make this a type 19 custom action +> if( sourceBits == 0 && targetBits == MsiInterop.MsidbCustomActionTypeTextData ) +> { +> sourceBits = MsiInterop.MsidbCustomActionTypeSourceFile; +> } +> +3881c3887 +< minDate = attrib.Value; +--- +> minDate = Common.GetFileTimeFromDateTime( attrib.Value ).ToString(); +3884c3890 +< maxDate = attrib.Value; +--- +> maxDate = Common.GetFileTimeFromDateTime( attrib.Value ).ToString(); +8187a8194,8207 +> case "Delete": +> switch (attrib.Value) +> { +> case "install": +> events |= MsiInterop.MsidbServiceControlEventDelete; +> break; +> case "uninstall": +> events |= MsiInterop.MsidbServiceControlEventUninstallDelete; +> break; +> case "both": +> events |= MsiInterop.MsidbServiceControlEventDelete | MsiInterop.MsidbServiceControlEventUninstallDelete; +> break; +> } +> break; +9685a9706 +> Index: src/wix/Preprocessor.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Preprocessor.cs,v -retrieving revision 1.5 -diff -u -w -r1.5 Preprocessor.cs ---- src/wix/Preprocessor.cs 28 Jul 2004 15:50:22 -0000 1.5 -+++ src/wix/Preprocessor.cs 4 Aug 2004 16:28:16 -0000 -@@ -267,12 +267,12 @@ - break; - case "ifdef": - stack.Push(context); -- context = new IfContext(context.IsTrue & context.Active, this.variables.ContainsKey(reader.Value.Trim()), IfState.If); -+ context = new IfContext(context.IsTrue & context.Active, this.IsDefined(reader.Value.Trim()), IfState.If); - ignore = true; - break; - case "ifndef": - stack.Push(context); -- context = new IfContext(context.IsTrue & context.Active, !this.variables.ContainsKey(reader.Value.Trim()), IfState.If); -+ context = new IfContext(context.IsTrue & context.Active, !this.IsDefined(reader.Value.Trim()), IfState.If); - ignore = true; - break; - case "elseif": -@@ -354,6 +354,8 @@ - break; - case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error - throw new WixPreprocessorException(this.GetCurrentSourceLineNumbers(), "Cannot have a processing instruction without a matching ."); -+ case "error": -+ throw new WixPreprocessorException(this.GetCurrentSourceLineNumbers(), this.PreprocessVariables(reader.Value)); - default: - // Console.WriteLine("processing instruction: {0}, {1}", reader.Name, reader.Value); - break; -@@ -401,6 +403,22 @@ - } - - /// -+ /// Returns true if the symbol exists. -+ /// -+ /// symbol name to check -+ /// true if symbol is defined -+ private bool IsDefined(string symbol) -+ { -+ if( symbol.StartsWith("env.") ) -+ return Environment.GetEnvironmentVariable(symbol.Substring(4)) != null; -+ if( symbol.StartsWith("var.") ) -+ return this.variables.ContainsKey(symbol.Substring(4)); -+ if( symbol.StartsWith("sys.") ) -+ return this.systemVariables.ContainsKey(symbol.Substring(4)); -+ return this.variables.ContainsKey(symbol); -+ } -+ -+ /// - /// Replaces parameters in the source text. - /// - /// Text that may contain parameters to replace. +retrieving revision 1.6 +diff -w -r1.6 Preprocessor.cs +274c274 +< context = new IfContext(context.IsTrue & context.Active, this.variables.ContainsKey(reader.Value.Trim()), IfState.If); +--- +> context = new IfContext(context.IsTrue & context.Active, this.IsDefined(reader.Value.Trim()), IfState.If); +279c279 +< context = new IfContext(context.IsTrue & context.Active, !this.variables.ContainsKey(reader.Value.Trim()), IfState.If); +--- +> context = new IfContext(context.IsTrue & context.Active, !this.IsDefined(reader.Value.Trim()), IfState.If); +360a361,362 +> case "error": +> throw new WixPreprocessorException(this.GetCurrentSourceLineNumbers(), this.PreprocessVariables(reader.Value)); +419a422,437 +> /// Returns true if the symbol exists. +> /// +> /// symbol name to check +> /// true if symbol is defined +> private bool IsDefined(string symbol) +> { +> if( symbol.StartsWith("env.") ) +> return Environment.GetEnvironmentVariable(symbol.Substring(4)) != null; +> if( symbol.StartsWith("var.") ) +> return this.variables.ContainsKey(symbol.Substring(4)); +> if( symbol.StartsWith("sys.") ) +> return this.systemVariables.ContainsKey(symbol.Substring(4)); +> return this.variables.ContainsKey(symbol); +> } +> +> /// Index: src/wix/wix.csproj =================================================================== RCS file: /cvsroot/wix/wix/src/wix/wix.csproj,v retrieving revision 1.4 -diff -u -w -r1.4 wix.csproj ---- src/wix/wix.csproj 31 May 2004 01:07:40 -0000 1.4 -+++ src/wix/wix.csproj 4 Aug 2004 16:28:16 -0000 -@@ -659,9 +659,19 @@ - BuildAction = "EmbeddedResource" - /> - -+ -+ - - - -Index: src/wix/Xsd/wix.xsd -=================================================================== -RCS file: /cvsroot/wix/wix/src/wix/Xsd/wix.xsd,v -retrieving revision 1.12 -diff -u -w -r1.12 wix.xsd ---- src/wix/Xsd/wix.xsd 28 Jul 2004 15:50:24 -0000 1.12 -+++ src/wix/Xsd/wix.xsd 4 Aug 2004 16:28:17 -0000 -@@ -2733,6 +2733,7 @@ - - - -+ - - - +diff -w -r1.4 wix.csproj +661a662,666 +> RelPath = "Xsd\wix.xsx" +> DependentUpon = "wix.xsd" +> BuildAction = "None" +> /> +> RelPath = "Xsd\wixloc.xsx" +> DependentUpon = "wixloc.xsd" +> BuildAction = "None" +> /> STEP J. Build Wix MSI install package -From the DOS command prompt window run: +From the %AFSROOT% directory execute: nmake /f NTMakefile wix @@ -442,7 +424,7 @@ STEP K. Final Results The build process generates its binaries in %AFSROOT%\DEST. The subdirectory would look like the following: -%AFSROOT%:\DEST\{checked,free}\ +%AFSROOT%\DEST\{checked,free}\ bin etc include @@ -454,7 +436,8 @@ would look like the following: Bin - contains build utilities. root.client - contains Open AFS binaries root.server - contain Open AFS Server binaries - WinInstall\OpenAFSforWindows.exe - is the install package for Open AFS + WinInstall\OpenAFSforWindows.exe - is the NSIS install package + WinInstall\openafs-en_US.msi - is the WiX MSI install package STEP L. Optional Items diff --git a/doc/txt/winnotes/afs-changes-since-1.2.txt b/doc/txt/winnotes/afs-changes-since-1.2.txt index 0356e0cc7..6f10f591d 100644 --- a/doc/txt/winnotes/afs-changes-since-1.2.txt +++ b/doc/txt/winnotes/afs-changes-since-1.2.txt @@ -1,3 +1,31 @@ +Since 1.3.72/73: + * Fix the locking of objects during Directory Searches in the + SMB/CIFS server. The failure to properly lock the reference + counts was resulting in the premature freeing of smb_dirSearch_t + objects while they were still in use by the SMB/CIFS client. + This does not solve the "Invalid Handle" problem. + + * Fix Find Cell By Name pioctl call to return a valid cell + name for the Freelance fake root.afs volume. + "Freelance.Local.Root". + + * Fix the Explorer Shell Extension Symlinks->Add operation. + The dialog template was missing and the link destination + string was too short. + + * Add support for symlinks to Freelance root.afs volume + Stored at HKLM\SOFTWARE\OpenAFS\Client\Freelance\Symlinks + = ":." + Use symlink.exe to create, list, or remove + + * Remove the fallback to the use of KFW's KRB4 library when obtaining + tokens. We never obtain KRB4 tickets. + + * Fix AFS Client Configuration Control Panel to support new SysName + protocol. + * Fix a bug in afsd_service.exe which could result in the SysName + not being read from the registry. + Since 1.3.71: * Add code to block the issuance of AFS tokens by aklog.exe or afscreds.exe when the Kerberos 5 principal name contains a dot. diff --git a/doc/txt/winnotes/afs-install-notes.txt b/doc/txt/winnotes/afs-install-notes.txt index 49f8f743c..d2e2cf1d9 100644 --- a/doc/txt/winnotes/afs-install-notes.txt +++ b/doc/txt/winnotes/afs-install-notes.txt @@ -1,4 +1,4 @@ -OpenAFS for Windows 1.3.72 Installation Notes +OpenAFS for Windows 1.3.74 Installation Notes --------------------------------------------- The OpenAFS for Windows product was very poorly maintained throughout the @@ -72,24 +72,38 @@ The OpenAFS Client Service now supports a fake "root.afs" volume which is dynamically constructed when the service starts. This mode is called Freelance mode. Freelance mode is turned on by default. -The contents of the -fake "root.afs" volume are constructed dynamically as cells are accessed. -When the fake "root.afs" volume is constructed it will only contain two -mount points: a read-only and read-write mount point used to access the -"root.cell" volume of the default AFS cell. Any attempt to access a -valid cell name will automatically result in a new mount point +The contents of the fake "root.afs" volume are constructed dynamically as +cells are accessed. When the fake "root.afs" volume is constructed it will +only contain two mount points: a read-only and read-write mount point used +to access the "root.cell" volume of the default AFS cell. Any attempt to +access a valid cell name will automatically result in a new mount point being created in the fake "root.afs" volume. If the cellname begins with a "." the mount point will be read-write; otherwise the mount point will be read-only. These mount points are preserved in the registry at key: + HKLM\SOFTWARE\OpenAFS\Client\Freelance Additional mount points may be manually created using the "fs mkmount" command. Mount points may be removed using the "fs rmmount" command. - fs mkmount \\AFS\all\athena.mit.edu root.cell athena.mit.edu - fs mkmount \\AFS\all\.athena.mit.edu root.cell athena.mit.edu -rw - fs rmmount \\AFS\all\athena.mit.edu - fs rmmount \\AFS\all\.athena.mit.edu + >fs mkmount \\AFS\all\athena.mit.edu root.cell athena.mit.edu + >fs mkmount \\AFS\all\.athena.mit.edu root.cell athena.mit.edu -rw + >fs rmmount \\AFS\all\athena.mit.edu + >fs rmmount \\AFS\all\.athena.mit.edu + +Beginning in 1.3.74, the Freelance fake root.afs volume will support +the creation of symlinks. + + >symlink make \\afs\all\link \\afs\all\athena.mit.edu\user\j\a\jaltman + + >symlink list \\afs\all\link + '\\afs\all\link' is a symlink to 'athena.mit.edu\user\j\a\jaltman' + + >symlink rm \\afs\all\link + +The symlinks are stored in the registry at: + + HKLM\SOFTWARE\OpenAFS\Client\Freelance\Symlinks 4. The OpenAFS for Windows client will use AFSDB DNS records to @@ -358,6 +372,19 @@ the availability of this option should only be used by individuals until such time as their organizations can provide a more permanent solution. +25. The Status Cache (AFS Config Control Panel: Advanced Page) is defined +to have a maximum number of entries. Each entry represents a single file +or directory entry accessed within the AFS file system. When the maximum +number of entries are allocated, entries will begin to be reused according +to a least recently used (LRU) algorithm. If the number of files or +directories being accessed repeatedly by your applications is greater then +the maximum number of entries, your host will begin to experience thrashing +of the Status Cache and all requests will result in network operations. + +If you are experiencing poor performance you might want to increase the +maximum number of Status Cache entries. Each entry requires 164K. Only +those entries which are used are allocated. + ------------------------------------------------------------------------ diff --git a/doc/txt/winnotes/afs-issues.txt b/doc/txt/winnotes/afs-issues.txt index 44e53c950..55b8a9b33 100644 --- a/doc/txt/winnotes/afs-issues.txt +++ b/doc/txt/winnotes/afs-issues.txt @@ -73,6 +73,8 @@ directories. description must be unique. "home" cannot be reused. We need a way to remove "home" from the submount list. + [Actually, an end user should not be able to modify the submount list] + (16) WinAFS configuration values are still stored in old style INI files instead of using the Registry. This is especially important for per-user values such as drive mappings @@ -115,20 +117,30 @@ directories. can be executed prior to the completion of the SMB registration and service thread initialization. -(28) Should we allow the AFSCACHE file to be stored in the Virtual Paging - file as long as we do not support persistent caches? - -(29) CIFS Remote Administration Protocol implementation is incomplete. +(28) CIFS Remote Administration Protocol implementation is incomplete. Notifications are not made to requestors when the view of a file or folder changes due to token acquisition; token expiration; or token destruction -(30) Microsoft Office appears to have trouble editing files of ~20MB - or larger from within AFS. Performance is particularly slow and - applications such as Word often crash upon saving the files. +(29) The Cache Manager Flush routines do not return or check error + codes. + +(30) Remove submount creation as a side effect of AFS drive mapping. + + The AFS Submount is effectively a server side alias for a path + located in the AFS space. This alias is exported by the AFS + SMB/CIFS Server to the Windows SMB/CIFS client as a Share name. + This makes the AFS Submount a system global setting which should + only be modified by a member of the "AFS Client Admin" group. -(31) The Cache Manager Flush routines do not return or check error - codes. + afs_creds.exe and afs_config.exe should be modified to no longer + use submount names when creating drive maps. Drive maps should + simply use the full AFS path name. Submounts should not be + created as a side effect of a drive mapping. + + The creation of submounts should only be possible via afsshare.exe + or by the new AFS Client Service Administration tool when executed + by an authorized user. ------------------------------------------------------------------------- List of unfunded projects: @@ -155,7 +167,7 @@ List of unfunded projects: 8. Re-write afs_config.exe to be only "per user" functionality which does not require admin privileges 1. default cell and principal for the user - 2. drive mappings + 2. drive mappings but no submounts 3. visibility of afs creds and setting of afs creds startup options 9. Create new afs_admin.exe tool to be installed in the administrator folder (or use MMS) which contains @@ -176,7 +188,7 @@ List of unfunded projects: 11. Add support for configurable Icon file representing AFS folders within the Explorer Shell 12. Documentation Documentation Documentation 13. Large File support (> 2GB) - 14. Integrate KFW installation into the NSIS installer + 14. Integrate KFW installation into the NSIS and MSI installers 15. Add support for record locking to AFS (requires changes to the servers) 16. Unicode enable the SMB/CIFS server. OEM Code Pages: 1. prevent the use of interoperable file names @@ -184,17 +196,12 @@ List of unfunded projects: 3. force share names to be no longer than 13 characters 4. restrict authentication to ASCII only names and passwords 17. Complete implementation of CIFS Remote Administration Protocol - 18. Correct the problems with overlapped writes which adversely affect - Microsoft Office applications storing documents and temporary files - within AFS volumes 19. Add support for SMB/CIFS Digital Signatures - 20. Development of afsmap.exe tool to provide AFS aware NET USE functionality + 19. Development of afsmap.exe tool to provide AFS aware NET USE functionality afsmap.exe [/PERSISTENT] afsmap.exe [/PERSISTENT] afsmap.exe /DELETE - 21. Write-through caching appears to be unsupported. Files copied to AFS - do not end up in the local cache. - 22. Missing SMB/CIFS functions: + 20. Missing SMB/CIFS functions: Find FindUnique FindClose @@ -202,11 +209,14 @@ List of unfunded projects: WriteBulk WriteBulkData Tran2::SessionSetup - 23. StoreBehind mode is not implemented. Or more correctly, all data is + 21. StoreBehind mode is not implemented. Or more correctly, all data is written directly to the server and is not cached. Writes invalidate the local cache entries which are then read back from the server. - 24. The Power Management Flush Cache code does not work on Terminal + 22. The Power Management Flush Cache code does not work on Terminal Server nor does it always successfully flush all of the dirty buffers to the AFS servers before suspend/hibernate operations occur. - - + 23. Develop an optional Installable File System replacement for the SMB/CIFS + Server. + 24. Add support for storing Extended Attributes on files + 25. Add support for storing Windows ACLs on files + 26. Remove submount creation as a side effect of drive creation diff --git a/doc/txt/winnotes/registry.txt b/doc/txt/winnotes/registry.txt index 9e5d2455a..fcf21131d 100644 --- a/doc/txt/winnotes/registry.txt +++ b/doc/txt/winnotes/registry.txt @@ -733,16 +733,33 @@ Value : "numeric value" Type : REG_SZ Default : - This key is used to store newline terminated mount point strings + This key is used to store dot terminated mount point strings for use in constructing the fake root.afs volume when Freelance (dynamic roots) mode is activated. - "athena.mit.edu#athena.mit.edu:root.cell.\n" - ".athena.mit.edu%athena.mit.edu:root.cell.\n" + "athena.mit.edu#athena.mit.edu:root.cell." + ".athena.mit.edu%athena.mit.edu:root.cell." These values used to be stored in afs_freelance.ini +Regkey: +[HKLM\SOFTWARE\OpenAFS\Client\Freelance\Symlinks] + +Value : "numeric value" +Type : REG_SZ +Default : + + This key is used to store a dot terminated symlink strings + for use in constructing the fake root.afs volume when Freelance + (dynamic roots) mode is activated. + + "linkname:destination-path." + "athena:athena.mit.edu." + "home:athena.mit.edu\user\j\a\jaltman." + "filename:path\file." + + Regkey: [HKLM\SOFTWARE\OpenAFS\Client\Submounts] diff --git a/src/WINNT/afsapplib/NTMakefile b/src/WINNT/afsapplib/NTMakefile index e4503835b..3b757ec6d 100644 --- a/src/WINNT/afsapplib/NTMakefile +++ b/src/WINNT/afsapplib/NTMakefile @@ -126,6 +126,9 @@ $(DLLFILE) : $(DLLOBJS) $(DLLLIBS) $(DEL) $*.lib $*.exp clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. ############################################################################ diff --git a/src/WINNT/afsd/NTMakefile b/src/WINNT/afsd/NTMakefile index 7f325edd3..4797139ec 100644 --- a/src/WINNT/afsd/NTMakefile +++ b/src/WINNT/afsd/NTMakefile @@ -339,26 +339,26 @@ AFSD_EXEFILE = $(EXEDIR)\afsd.exe AFSD_SDKLIBS =\ largeint.lib \ netapi32.lib \ - dnsapi.lib mpr.lib \ + dnsapi.lib mpr.lib \ rpcrt4.lib \ user32.lib \ - Dbghelp.lib \ - strsafe.lib \ - mpr.lib \ - secur32.lib \ - ole32.lib \ - oleaut32.lib + Dbghelp.lib \ + strsafe.lib \ + mpr.lib \ + secur32.lib \ + ole32.lib \ + oleaut32.lib AFSD_EXELIBS =\ $(DESTDIR)\lib\libosi.lib \ $(DESTDIR)\lib\afsrpc.lib \ - $(DESTDIR)\lib\afsrx.lib \ + $(DESTDIR)\lib\afsrx.lib \ $(DESTDIR)\lib\afsauthent.lib \ $(DESTDIR)\lib\afs\mtafsvldb.lib \ $(DESTDIR)\lib\afs\mtafsint.lib \ $(DESTDIR)\lib\libafsconf.lib \ $(DESTDIR)\lib\afs\afsreg.lib \ - $(LANAHELPERLIB) + $(LANAHELPERLIB) $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res $(RXOBJS) $(AFSD_EXELIBS) $(EXEGUILINK) $(AFSD_SDKLIBS) diff --git a/src/WINNT/afsd/afsd.c b/src/WINNT/afsd/afsd.c index 8e29f678e..d8661ebbb 100644 --- a/src/WINNT/afsd/afsd.c +++ b/src/WINNT/afsd/afsd.c @@ -53,6 +53,7 @@ void afsd_notifier(char *msgp, char *filep, long line) MessageBox(NULL, tbuffer, msgp, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND); afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); if (traceOnPanic) { _asm int 3h; diff --git a/src/WINNT/afsd/afsd95.c b/src/WINNT/afsd/afsd95.c index 75cd53ae1..2b77da329 100644 --- a/src/WINNT/afsd/afsd95.c +++ b/src/WINNT/afsd/afsd95.c @@ -52,6 +52,7 @@ void afsd_notifier(char *msgp, char *filep, long line) /*MessageBox(NULL, tbuffer, msgp, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);*/ afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); if (traceOnPanic) { /*asm("int 3");*/ diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index a11118b94..8c3456849 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -22,7 +22,6 @@ #include "afsd.h" #include #include - #include #include "smb.h" @@ -651,7 +650,7 @@ int afsd_InitCM(char **reasonP) char * p, *q; afsi_log("Sys name %s", buf); - for (p = q = buf; p < cm_sysName + dummyLen; p++) + for (p = q = buf; p < buf + dummyLen; p++) { if (*p == '\0' || isspace(*p)) { memcpy(cm_sysNameList[cm_sysNameCount],q,p-q); diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index 43fcb783f..d9236c3dd 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -82,6 +82,7 @@ static void afsd_notifier(char *msgp, char *filep, long line) osi_LogEnable(afsd_logp); afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); afsi_log("--- begin dump ---"); cm_DumpSCache(afsi_file, "a"); @@ -176,8 +177,10 @@ afsd_ServiceControlHandler(DWORD ctrlCode) RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; - if (doTrace) + if (doTrace) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); + } doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; @@ -239,8 +242,10 @@ afsd_ServiceControlHandlerEx( RegCloseKey (parmKey); if (code != ERROR_SUCCESS) doTrace = 0; - if (doTrace) + if (doTrace) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); + } doneTrace: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; diff --git a/src/WINNT/afsd/afskfw.c b/src/WINNT/afsd/afskfw.c index 743374a28..01ace95a8 100644 --- a/src/WINNT/afsd/afskfw.c +++ b/src/WINNT/afsd/afskfw.c @@ -56,7 +56,7 @@ #define USE_MS2MIT -#define USE_KRB4 +#undef USE_KRB4 #include "afskfw-int.h" #include "afskfw.h" @@ -288,6 +288,7 @@ FUNC_INFO k5_fi[] = { END_FUNC_INFO }; +#ifdef USE_KRB4 FUNC_INFO k4_fi[] = { MAKE_FUNC_INFO(krb_get_cred), MAKE_FUNC_INFO(krb_get_tf_realm), @@ -295,6 +296,7 @@ FUNC_INFO k4_fi[] = { MAKE_FUNC_INFO(tkt_string), END_FUNC_INFO }; +#endif FUNC_INFO k524_fi[] = { MAKE_FUNC_INFO(krb524_init_ets), @@ -388,7 +390,9 @@ KFW_initialize(void) if ( !inited ) { inited = 1; LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); +#ifdef USE_KRB4 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0); +#endif /* USE_KRB4 */ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); #ifdef USE_MS2MIT @@ -457,20 +461,17 @@ KFW_use_krb524(void) len = sizeof(use524); code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, (BYTE *) &use524, &len); - if (code != ERROR_SUCCESS) { - RegCloseKey(parmKey); - - code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, - 0, KEY_QUERY_VALUE, &parmKey); - if (code == ERROR_SUCCESS) { - len = sizeof(use524); - code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, - (BYTE *) &use524, &len); - if (code != ERROR_SUCCESS) - use524 = 0; - } + RegCloseKey(parmKey); + } + if (code != ERROR_SUCCESS) { + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + len = sizeof(use524); + code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, + (BYTE *) &use524, &len); + RegCloseKey (parmKey); } - RegCloseKey (parmKey); } return use524; } @@ -488,21 +489,20 @@ KFW_is_available(void) len = sizeof(enableKFW); code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, (BYTE *) &enableKFW, &len); - if (code != ERROR_SUCCESS) { - RegCloseKey(parmKey); - - code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, - 0, KEY_QUERY_VALUE, &parmKey); - if (code == ERROR_SUCCESS) { - len = sizeof(enableKFW); - code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, - (BYTE *) &enableKFW, &len); - if (code != ERROR_SUCCESS) - enableKFW = 1; - } - } RegCloseKey (parmKey); } + + if (code != ERROR_SUCCESS) { + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + len = sizeof(enableKFW); + code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL, + (BYTE *) &enableKFW, &len); + RegCloseKey (parmKey); + } + } + if ( !enableKFW ) return FALSE; @@ -2643,7 +2643,8 @@ KFW_AFS_klog( } } #else - goto cleanup; + if (!try_krb5) + goto cleanup; #endif strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig)); @@ -2700,7 +2701,7 @@ KFW_AFS_klog( code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds); if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || - code == KRB5KRB_AP_ERR_MSG_TYPE) { + code == KRB5KRB_AP_ERR_MSG_TYPE) { /* Or service@REALM */ pkrb5_free_principal(ctx,increds.server); increds.server = 0; @@ -2730,7 +2731,7 @@ KFW_AFS_klog( if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || code == KRB5KRB_ERR_GENERIC /* heimdal */ || - code == KRB5KRB_AP_ERR_MSG_TYPE) && + code == KRB5KRB_AP_ERR_MSG_TYPE) && strcmp(RealmName, realm_of_cell)) { /* Or service/cell@REALM_OF_CELL */ strcpy(RealmName, realm_of_cell); @@ -3021,7 +3022,7 @@ KFW_AFS_klog( if (ctx && (ctx != alt_ctx)) pkrb5_free_context(ctx); - return(rc? rc : code); + return(rc? rc : code); } /**************************************/ diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index b0cef02e8..423bdd30f 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -245,8 +245,9 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_BUFFERTOOSMALL (CM_ERROR_BASE+38) #define CM_ERROR_RENAME_IDENTICAL (CM_ERROR_BASE+39) #define CM_ERROR_ALLOFFLINE (CM_ERROR_BASE+40) -#define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) -#define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) -#define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) -#define CM_ERROR_TIDIPC (CM_ERROR_BASE+44) +#define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) +#define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) +#define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) +#define CM_ERROR_TIDIPC (CM_ERROR_BASE+44) +#define CM_ERROR_TOO_MANY_SYMLINKS (CM_ERROR_BASE+45) #endif /* __CM_H_ENV__ */ diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index 9fef57dfe..06c9cc162 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -19,9 +19,14 @@ #include #include #include +#include #include "afsd.h" +#ifdef DEBUG +#define TRACE_BUFFER 1 +#endif + extern void afsi_log(char *pattern, ...); /* This module implements the buffer package used by the local transaction @@ -306,12 +311,12 @@ long buf_Init(cm_buf_ops_t *opsp) OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + FreeCacheFileSA(psa); if (hf == INVALID_HANDLE_VALUE) { afsi_log("Error creating cache file \"%s\" error %d", cm_CachePath, GetLastError()); return CM_ERROR_INVAL; } - FreeCacheFileSA(psa); } else { /* buf_cacheType == CM_BUF_CACHETYPE_VIRTUAL */ hf = INVALID_HANDLE_VALUE; } @@ -378,8 +383,11 @@ long buf_Init(cm_buf_ops_t *opsp) /* just for safety's sake */ buf_maxReservedBufs = buf_nbuffers - 3; +#ifdef TRACE_BUFFER /* init the buffer trace log */ - buf_logp = osi_LogCreate("buffer", 10); + buf_logp = osi_LogCreate("buffer", 1000); + osi_LogEnable(buf_logp); +#endif osi_EndOnce(&once); @@ -532,7 +540,7 @@ void buf_WaitIO(cm_buf_t *bp) bp->flags |= CM_BUF_WAITING; osi_SleepM((long) bp, &bp->mx); lock_ObtainMutex(&bp->mx); - osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%x", bp); + osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%x", bp); } /* if we get here, the IO is done, but we may have to wakeup people waiting for @@ -1481,3 +1489,24 @@ int cm_DumpBufHashTable(FILE *outputFile, char *cookie) return 0; } +void buf_ForceTrace(BOOL flush) +{ + HANDLE handle; + int len; + char buf[256]; + + if (!buf_logp) + return; + + len = GetTempPath(sizeof(buf)-10, buf); + StringCbCopyA(&buf[len], sizeof(buf)-len, "/afs-buffer.log"); + handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + osi_panic("Cannot create log file", __FILE__, __LINE__); + } + osi_LogPrint(buf_logp, handle); + if (flush) + FlushFileBuffers(handle); + CloseHandle(handle); +} diff --git a/src/WINNT/afsd/cm_buf.h b/src/WINNT/afsd/cm_buf.h index 4ca977ad4..1f1bc42ac 100644 --- a/src/WINNT/afsd/cm_buf.h +++ b/src/WINNT/afsd/cm_buf.h @@ -195,6 +195,8 @@ extern long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, extern long buf_SetNBuffers(long nbuffers); +extern void buf_ForceTrace(BOOL flush); + /* error codes */ #define CM_BUF_EXISTS 1 /* buffer exists, and shouldn't */ #define CM_ERROR_BASEBUF 0x33333333 diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 32e748ad1..4dbfb2cfd 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -384,12 +384,12 @@ out: long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, cm_req_t *reqp, cm_conn_t **connpp) { - long code; - cm_serverRef_t *tsrp; + long code; + cm_serverRef_t *tsrp; cm_server_t *tsp; long firstError = 0; - int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1; - long timeUsed, timeLeft, hardTimeLeft; + int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1; + long timeUsed, timeLeft, hardTimeLeft; #ifdef DJGPP struct timeval now; #endif /* DJGPP */ @@ -397,17 +397,17 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, *connpp = NULL; #ifndef DJGPP - timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; + timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; #else gettimeofday(&now, NULL); timeUsed = sub_time(now, reqp->startTime) / 1000; #endif - /* leave 5 seconds margin of safety */ - timeLeft = ConnDeadtimeout - timeUsed - 5; - hardTimeLeft = HardDeadtimeout - timeUsed - 5; + /* leave 5 seconds margin of safety */ + timeLeft = ConnDeadtimeout - timeUsed - 5; + hardTimeLeft = HardDeadtimeout - timeUsed - 5; - lock_ObtainWrite(&cm_serverLock); + lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { tsp = tsrp->server; cm_GetServerNoLock(tsp); @@ -419,7 +419,7 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, else if (tsrp->status == offline) someOffline = 1; else { - allBusy = 0; + allBusy = 0; code = cm_ConnByServer(tsp, usersp, connpp); if (code == 0) { cm_PutServer(tsp); @@ -439,24 +439,24 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, if (firstError == 0) firstError = code; } - } + } lock_ObtainWrite(&cm_serverLock); cm_PutServerNoLock(tsp); } - lock_ReleaseWrite(&cm_serverLock); - if (firstError == 0) { + lock_ReleaseWrite(&cm_serverLock); + if (firstError == 0) { if (serversp == NULL) - firstError = CM_ERROR_NOSUCHVOLUME; + firstError = CM_ERROR_NOSUCHVOLUME; else if (allDown) - firstError = CM_ERROR_ALLOFFLINE; - else if (allBusy) - firstError = CM_ERROR_ALLBUSY; - else - firstError = CM_ERROR_TIMEDOUT; - } + firstError = CM_ERROR_ALLOFFLINE; + else if (allBusy) + firstError = CM_ERROR_ALLBUSY; + else + firstError = CM_ERROR_TIMEDOUT; + } - osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError); + osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError); return firstError; } diff --git a/src/WINNT/afsd/cm_freelance.c b/src/WINNT/afsd/cm_freelance.c index 2933c0f50..0894791a1 100644 --- a/src/WINNT/afsd/cm_freelance.c +++ b/src/WINNT/afsd/cm_freelance.c @@ -73,6 +73,45 @@ void cm_FreelanceChangeNotifier(void * parmp) { } } } + +void cm_FreelanceSymlinkChangeNotifier(void * parmp) { + HANDLE hFreelanceSymlinkChangeEvent = 0; + HKEY hkFreelance = 0; + + if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + KEY_NOTIFY, + &hkFreelance) == ERROR_SUCCESS) { + + hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hFreelanceSymlinkChangeEvent == NULL) { + RegCloseKey(hkFreelance); + return; + } + } + + while ( TRUE ) { + /* check hFreelanceSymlinkChangeEvent to see if it is set. + * if so, call cm_noteLocalMountPointSymlinkChange() + */ + if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */ + FALSE, /* bWatchSubtree */ + REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */ + hFreelanceSymlinkChangeEvent, /* hEvent */ + TRUE /* fAsynchronous */ + ) != ERROR_SUCCESS) { + RegCloseKey(hkFreelance); + CloseHandle(hFreelanceSymlinkChangeEvent); + return; + } + + if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0) + { + cm_noteLocalMountPointChange(); + } + } +} #endif void cm_InitFreelance() { @@ -98,13 +137,17 @@ void cm_InitFreelance() { NULL, 0, &lpid, "cm_FreelanceChangeNotifier"); osi_assert(phandle != NULL); thrd_CloseHandle(phandle); + + phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier, + NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier"); + osi_assert(phandle != NULL); + thrd_CloseHandle(phandle); #endif } /* yj: Initialization of the fake root directory */ /* to be called while holding freelance lock unless during init. */ void cm_InitFakeRootDir() { - int i, t1, t2; char* currentPos; int noChunks; @@ -398,12 +441,12 @@ long cm_InitLocalMountPoints() { long code; char rootCellName[256]; #if !defined(DJGPP) - HKEY hkFreelance = 0; + HKEY hkFreelance = 0, hkFreelanceSymlinks = 0; DWORD dwType, dwSize; - DWORD dwMountPoints; + DWORD dwMountPoints = 0; DWORD dwIndex; + DWORD dwSymlinks = 0; FILETIME ftLastWriteTime; - afs_uint32 unixTime; #endif #if !defined(DJGPP) @@ -440,9 +483,34 @@ long cm_InitLocalMountPoints() { dwMountPoints = 2; } + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + NULL, + &hkFreelanceSymlinks, + NULL) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + } + // get the number of entries there are from the first line // that we read - cm_noLocalMountPoints = dwMountPoints; + cm_noLocalMountPoints = dwMountPoints + dwSymlinks; // create space to store the local mount points cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints); @@ -478,14 +546,16 @@ long cm_InitLocalMountPoints() { cm_noLocalMountPoints--; continue; } + + aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT; aLocalMountPoint->namep=malloc(t-line+1); strncpy(aLocalMountPoint->namep, line, t-line); aLocalMountPoint->namep[t-line] = '\0'; - /* copy the mount point string without the trailing dot */ + /* copy the mount point string */ aLocalMountPoint->mountPointStringp=malloc(strlen(t)); - strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1); - aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0'; + strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1); + aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0'; osi_Log2(afsd_logp,"found mount point: name %s, string %s", osi_LogSaveString(afsd_logp,aLocalMountPoint->namep), @@ -494,6 +564,48 @@ long cm_InitLocalMountPoints() { aLocalMountPoint++; } + for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) { + TCHAR szValueName[16]; + DWORD dwValueSize = 16; + dwSize = sizeof(line); + RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL, + &dwType, line, &dwSize); + + /* find the trailing dot; null terminate after it */ + t2 = strrchr(line, '.'); + if (t2) + *(t2+1) = '\0'; + + // line is not empty, so let's parse it + t = strchr(line, ':'); + + // make sure that there is a ':' separator in the line + if (!t) { + afsi_log("error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex); + fprintf(stderr, "error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex); + cm_noLocalMountPoints--; + continue; + } + + aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK; + aLocalMountPoint->namep=malloc(t-line+1); + strncpy(aLocalMountPoint->namep, line, t-line); + aLocalMountPoint->namep[t-line] = '\0'; + + /* copy the symlink string */ + aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1); + strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2); + aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0'; + + osi_Log2(afsd_logp,"found symlink: name %s, string %s", + osi_LogSaveString(afsd_logp,aLocalMountPoint->namep), + osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp)); + + aLocalMountPoint++; + } + + if ( hkFreelanceSymlinks ) + RegCloseKey( hkFreelanceSymlinks ); RegCloseKey(hkFreelance); return 0; } @@ -625,10 +737,6 @@ int cm_getNoLocalMountPoints() { return cm_noLocalMountPoints; } -cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) { - return 0; -} - long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp) { FILE *fp; @@ -688,22 +796,35 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, ); if (rw) - sprintf(line, "%s%%%s:%s\n", filename, fullname, volume); + sprintf(line, "%s%%%s:%s", filename, fullname, volume); else - sprintf(line, "%s#%s:%s\n", filename, fullname, volume); + sprintf(line, "%s#%s:%s", filename, fullname, volume); /* If we are adding a new value, there must be an unused name * within the range 0 to dwMountPoints */ for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) { char szIndex[16]; + char szMount[1024]; + + dwSize = sizeof(szMount); sprintf(szIndex, "%d", dwIndex); - if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, NULL, &dwSize) != ERROR_SUCCESS) { + if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) { /* found an unused value */ dwType = REG_SZ; dwSize = strlen(line) + 1; RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize); break; + } else { + int len = strlen(filename); + if ( dwType == REG_SZ && !strncmp(filename, szMount, len) && + (szMount[len] == '%' || szMount[len] == '#')) { + /* Replace the existing value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize); + break; + } } } RegCloseKey(hkFreelance); @@ -847,4 +968,160 @@ long cm_FreelanceRemoveMount(char *toremove) return 0; } +long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp) +{ + FILE *fp; + char hfile[120]; + char line[512]; + char fullname[200]; + int n; + int alias = 0; +#if !defined(DJGPP) + HKEY hkFreelanceSymlinks = 0; + DWORD dwType, dwSize; + DWORD dwSymlinks; + DWORD dwIndex; +#endif + + /* before adding, verify the cell name; if it is not a valid cell, + don't add the mount point. + allow partial matches as a means of poor man's alias. */ + /* major performance issue? */ + osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s", + osi_LogSaveString(afsd_logp,filename), + osi_LogSaveString(afsd_logp,destination)); + + lock_ObtainMutex(&cm_Freelance_Lock); + +#if !defined(DJGPP) + if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + NULL, + &hkFreelanceSymlinks, + NULL) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + + sprintf(line, "%s:%s.", filename, destination); + + /* If we are adding a new value, there must be an unused name + * within the range 0 to dwSymlinks + */ + for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) { + char szIndex[16]; + char szLink[1024]; + + dwSize = sizeof(szLink); + sprintf(szIndex, "%d", dwIndex); + if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) { + /* found an unused value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize); + break; + } else { + int len = strlen(filename); + if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') { + /* Replace the existing value */ + dwType = REG_SZ; + dwSize = strlen(line) + 1; + RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize); + break; + } + } + } + RegCloseKey(hkFreelanceSymlinks); + } +#endif + lock_ReleaseMutex(&cm_Freelance_Lock); + + /* cm_reInitLocalMountPoints(); */ + if (fidp) { + fidp->unique = 1; + fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */ + } + cm_noteLocalMountPointChange(); + return 0; +} + +long cm_FreelanceRemoveSymlink(char *toremove) +{ + int i, n; + char* cp; + char line[512]; + char shortname[200]; + char hfile[120], hfile2[120]; + FILE *fp1, *fp2; + int found=0; +#if !defined(DJGPP) + HKEY hkFreelanceSymlinks = 0; + DWORD dwType, dwSize; + DWORD dwSymlinks; + DWORD dwIndex; +#endif + + lock_ObtainMutex(&cm_Freelance_Lock); + + +#if !defined(DJGPP) + if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, + "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks", + 0, + KEY_READ|KEY_WRITE|KEY_QUERY_VALUE, + &hkFreelanceSymlinks) == ERROR_SUCCESS) { + + RegQueryInfoKey( hkFreelanceSymlinks, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + NULL, /* lpcSubKeys */ + NULL, /* lpcMaxSubKeyLen */ + NULL, /* lpcMaxClassLen */ + &dwSymlinks, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ + ); + + for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) { + TCHAR szValueName[16]; + DWORD dwValueSize = 16; + dwSize = sizeof(line); + RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL, + &dwType, line, &dwSize); + + cp=strchr(line, ':'); + memcpy(shortname, line, cp-line); + shortname[cp-line]=0; + + if (!strcmp(shortname, toremove)) { + RegDeleteValue( hkFreelanceSymlinks, szValueName ); + break; + } + } + RegCloseKey(hkFreelanceSymlinks); + } +#endif + + lock_ReleaseMutex(&cm_Freelance_Lock); + cm_noteLocalMountPointChange(); + return 0; +} #endif /* AFS_FREELANCE_CLIENT */ diff --git a/src/WINNT/afsd/cm_freelance.h b/src/WINNT/afsd/cm_freelance.h index 3d02b9e09..effeb9ee6 100644 --- a/src/WINNT/afsd/cm_freelance.h +++ b/src/WINNT/afsd/cm_freelance.h @@ -3,19 +3,21 @@ typedef struct cm_localMountPoint { - char* namep; - char* mountPointStringp; - struct cm_localMountPoint* next; + char* namep; + char* mountPointStringp; + unsigned int fileType; + struct cm_localMountPoint* next; } cm_localMountPoint_t; extern int cm_getNoLocalMountPoints(); extern long cm_InitLocalMountPoints(); extern int cm_getLocalMountPointChange(); extern int cm_reInitLocalMountPoints(); -extern cm_localMountPoint_t* cm_getLocalMountPoint(int vnode); extern void cm_InitFreelance(); extern long cm_FreelanceRemoveMount(char *toremove); extern long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp); +extern long cm_FreelanceRemoveSymlink(char *toremove); +extern long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp); extern int cm_clearLocalMountPointChange(); extern int cm_FakeRootFid(cm_fid_t *fidp); diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 13bd7a48f..bb60b77e6 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -458,13 +458,26 @@ long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp) code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp); if (code) return code; - cellp = cm_FindCellByID(scp->fid.cell); - if (cellp) { - strcpy(ioctlp->outDatap, cellp->namep); +#ifdef AFS_FREELANCE_CLIENT + if ( cm_freelanceEnabled && + scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && + scp->fid.volume==AFS_FAKE_ROOT_VOL_ID && + scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) { + strcpy(ioctlp->outDatap, "Freelance.Local.Root"); ioctlp->outDatap += strlen(ioctlp->outDatap) + 1; code = 0; + } else +#endif /* AFS_FREELANCE_CLIENT */ + { + cellp = cm_FindCellByID(scp->fid.cell); + if (cellp) { + strcpy(ioctlp->outDatap, cellp->namep); + ioctlp->outDatap += strlen(ioctlp->outDatap) + 1; + code = 0; + } + else + code = CM_ERROR_NOSUCHCELL; } - else code = CM_ERROR_NOSUCHCELL; cm_ReleaseSCache(scp); return code; @@ -983,6 +996,7 @@ long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp) /* print trace */ if (inValue & 8) { afsd_ForceTrace(FALSE); + buf_ForceTrace(FALSE); } if (inValue & 2) { @@ -1213,6 +1227,7 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp) * do lookups of @sys entries and thinks it can trust them */ /* privs ok, store the entry, ... */ strcpy(cm_sysName, inname); + strcpy(cm_sysNameList[0], inname); if (setSysName > 1) { /* ... or list */ cp = ioctlp->inDatap; for (count = 1; count < setSysName; ++count) { @@ -1220,7 +1235,7 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp) osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n", __FILE__, __LINE__); t = strlen(cp); - memcpy(cm_sysNameList[count], cp, t + 1); /* include null */ + strcpy(cm_sysNameList[count], cp); cp += t + 1; } } @@ -1509,6 +1524,26 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) cp = ioctlp->inDatap; /* contents of link */ +#ifdef AFS_FREELANCE_CLIENT + if (cm_freelanceEnabled && dscp == cm_rootSCachep) { + /* we are adding the symlink to the root dir., so call + * the freelance code to do the add. */ + if (cp[0] == cp[1] && cp[1] == '\\' && + !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName))) + { + /* skip \\AFS\ or \\AFS\all\ */ + char * p; + p = cp + 2 + strlen(cm_NetbiosName) + 1; + if ( !_strnicmp("all", p, 3) ) + p += 4; + cp = p; + } + osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir"); + code = cm_FreelanceAddSymlink(leaf, cp, NULL); + return code; + } +#endif + /* Create symlink with mode 0755. */ tattr.mask = CM_ATTRMASK_UNIXMODEBITS; tattr.unixModeBits = 0755; @@ -1618,6 +1653,16 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp) cp = ioctlp->inDatap; +#ifdef AFS_FREELANCE_CLIENT + if (cm_freelanceEnabled && dscp == cm_rootSCachep) { + /* we are adding the mount point to the root dir., so call + * the freelance code to do the add. */ + osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir"); + code = cm_FreelanceRemoveSymlink(cp); + return code; + } +#endif + code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp); /* if something went wrong, bail out now */ diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index b1d29854c..b5e2a7626 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -52,10 +52,10 @@ extern osi_mutex_t cm_Freelance_Lock; /* must be called with cm_scacheLock write-locked! */ void cm_AdjustLRU(cm_scache_t *scp) { - if (scp == cm_scacheLRULastp) - cm_scacheLRULastp = (cm_scache_t *) osi_QPrev(&scp->q); - osi_QRemove((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); - osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); + if (scp == cm_scacheLRULastp) + cm_scacheLRULastp = (cm_scache_t *) osi_QPrev(&scp->q); + osi_QRemove((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); + osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; } @@ -65,118 +65,118 @@ void cm_AdjustLRU(cm_scache_t *scp) */ cm_scache_t *cm_GetNewSCache(void) { - cm_scache_t *scp; - int i; - cm_scache_t **lscpp; - cm_scache_t *tscp; - - if (cm_currentSCaches >= cm_maxSCaches) { - for (scp = cm_scacheLRULastp; - scp; - scp = (cm_scache_t *) osi_QPrev(&scp->q)) { + cm_scache_t *scp; + int i; + cm_scache_t **lscpp; + cm_scache_t *tscp; + + if (cm_currentSCaches >= cm_maxSCaches) { + for (scp = cm_scacheLRULastp; + scp; + scp = (cm_scache_t *) osi_QPrev(&scp->q)) { if (scp->refCount == 0) break; - } + } - if (scp) { - /* we found an entry, so return it */ - if (scp->flags & CM_SCACHEFLAG_INHASH) { - /* hash it out first */ - i = CM_SCACHE_HASH(&scp->fid); - lscpp = &cm_hashTablep[i]; - for (tscp = *lscpp; - tscp; - lscpp = &tscp->nextp, tscp = *lscpp) { + if (scp) { + /* we found an entry, so return it */ + if (scp->flags & CM_SCACHEFLAG_INHASH) { + /* hash it out first */ + i = CM_SCACHE_HASH(&scp->fid); + lscpp = &cm_hashTablep[i]; + for (tscp = *lscpp; + tscp; + lscpp = &tscp->nextp, tscp = *lscpp) { if (tscp == scp) break; - } - osi_assertx(tscp, "afsd: scache hash screwup"); - *lscpp = scp->nextp; - scp->flags &= ~CM_SCACHEFLAG_INHASH; - } - - /* look for things that shouldn't still be set */ - osi_assert(scp->bufWritesp == NULL); - osi_assert(scp->bufReadsp == NULL); - - /* invalidate so next merge works fine; - * also initialize some flags */ - scp->flags &= ~(CM_SCACHEFLAG_STATD - | CM_SCACHEFLAG_RO - | CM_SCACHEFLAG_PURERO - | CM_SCACHEFLAG_OVERQUOTA - | CM_SCACHEFLAG_OUTOFSPACE); - scp->serverModTime = 0; - scp->dataVersion = 0; - scp->bulkStatProgress = hzero; - - /* discard callback */ + } + osi_assertx(tscp, "afsd: scache hash screwup"); + *lscpp = scp->nextp; + scp->flags &= ~CM_SCACHEFLAG_INHASH; + } + + /* look for things that shouldn't still be set */ + osi_assert(scp->bufWritesp == NULL); + osi_assert(scp->bufReadsp == NULL); + + /* invalidate so next merge works fine; + * also initialize some flags */ + scp->flags &= ~(CM_SCACHEFLAG_STATD + | CM_SCACHEFLAG_RO + | CM_SCACHEFLAG_PURERO + | CM_SCACHEFLAG_OVERQUOTA + | CM_SCACHEFLAG_OUTOFSPACE); + scp->serverModTime = 0; + scp->dataVersion = 0; + scp->bulkStatProgress = hzero; + + /* discard callback */ if (scp->cbServerp) { cm_PutServer(scp->cbServerp); - scp->cbServerp = NULL; + scp->cbServerp = NULL; } - scp->cbExpires = 0; - - /* remove from dnlc */ - cm_dnlcPurgedp(scp); - cm_dnlcPurgevp(scp); - - /* discard cached status; if non-zero, Close - * tried to store this to server but failed */ - scp->mask = 0; - - /* drop held volume ref */ - if (scp->volp) { - cm_PutVolume(scp->volp); - scp->volp = NULL; - } - - /* discard symlink info */ - if (scp->mountPointStringp) { - free(scp->mountPointStringp); - scp->mountPointStringp = NULL; - } - if (scp->mountRootFidp) { - free(scp->mountRootFidp); - scp->mountRootFidp = NULL; - } - if (scp->dotdotFidp) { - free(scp->dotdotFidp); - scp->dotdotFidp = NULL; - } - - /* not locked, but there can be no references to this guy - * while we hold the global refcount lock. - */ - cm_FreeAllACLEnts(scp); - - /* now remove from the LRU queue and put it back at the - * head of the LRU queue. - */ - cm_AdjustLRU(scp); - - /* and we're done */ - return scp; - } - } + scp->cbExpires = 0; + + /* remove from dnlc */ + cm_dnlcPurgedp(scp); + cm_dnlcPurgevp(scp); + + /* discard cached status; if non-zero, Close + * tried to store this to server but failed */ + scp->mask = 0; + + /* drop held volume ref */ + if (scp->volp) { + cm_PutVolume(scp->volp); + scp->volp = NULL; + } + + /* discard symlink info */ + if (scp->mountPointStringp) { + free(scp->mountPointStringp); + scp->mountPointStringp = NULL; + } + if (scp->mountRootFidp) { + free(scp->mountRootFidp); + scp->mountRootFidp = NULL; + } + if (scp->dotdotFidp) { + free(scp->dotdotFidp); + scp->dotdotFidp = NULL; + } + + /* not locked, but there can be no references to this guy + * while we hold the global refcount lock. + */ + cm_FreeAllACLEnts(scp); + + /* now remove from the LRU queue and put it back at the + * head of the LRU queue. + */ + cm_AdjustLRU(scp); + + /* and we're done */ + return scp; + } + } - /* if we get here, we should allocate a new scache entry. We either are below - * quota or we have a leak and need to allocate a new one to avoid panicing. - */ - scp = malloc(sizeof(*scp)); - memset(scp, 0, sizeof(*scp)); - lock_InitializeMutex(&scp->mx, "cm_scache_t mutex"); - lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock"); - - /* and put it in the LRU queue */ - osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); + /* if we get here, we should allocate a new scache entry. We either are below + * quota or we have a leak and need to allocate a new one to avoid panicing. + */ + scp = malloc(sizeof(*scp)); + memset(scp, 0, sizeof(*scp)); + lock_InitializeMutex(&scp->mx, "cm_scache_t mutex"); + lock_InitializeRWLock(&scp->bufCreateLock, "cm_scache_t bufCreateLock"); + + /* and put it in the LRU queue */ + osi_QAdd((osi_queue_t **) &cm_scacheLRUFirstp, &scp->q); if (!cm_scacheLRULastp) cm_scacheLRULastp = scp; - cm_currentSCaches++; - cm_dnlcPurgedp(scp); /* make doubly sure that this is not in dnlc */ - cm_dnlcPurgevp(scp); - return scp; -} + cm_currentSCaches++; + cm_dnlcPurgedp(scp); /* make doubly sure that this is not in dnlc */ + cm_dnlcPurgevp(scp); + return scp; +} /* like strcmp, only for fids */ int cm_FidCmp(cm_fid_t *ap, cm_fid_t *bp) @@ -189,78 +189,78 @@ int cm_FidCmp(cm_fid_t *ap, cm_fid_t *bp) return 1; if (ap->cell != bp->cell) return 1; - return 0; + return 0; } void cm_fakeSCacheInit() { - memset(&cm_fakeSCache, 0, sizeof(cm_fakeSCache)); - lock_InitializeMutex(&cm_fakeSCache.mx, "cm_scache_t mutex"); - cm_fakeSCache.cbServerp = (struct cm_server *)(-1); - /* can leave clientModTime at 0 */ - cm_fakeSCache.fileType = CM_SCACHETYPE_FILE; - cm_fakeSCache.unixModeBits = 0777; - cm_fakeSCache.length.LowPart = 1000; - cm_fakeSCache.linkCount = 1; -} + memset(&cm_fakeSCache, 0, sizeof(cm_fakeSCache)); + lock_InitializeMutex(&cm_fakeSCache.mx, "cm_scache_t mutex"); + cm_fakeSCache.cbServerp = (struct cm_server *)(-1); + /* can leave clientModTime at 0 */ + cm_fakeSCache.fileType = CM_SCACHETYPE_FILE; + cm_fakeSCache.unixModeBits = 0777; + cm_fakeSCache.length.LowPart = 1000; + cm_fakeSCache.linkCount = 1; +} void cm_InitSCache(long maxSCaches) { - static osi_once_t once; + static osi_once_t once; - if (osi_Once(&once)) { - lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock"); - cm_hashTableSize = maxSCaches / 2; - cm_hashTablep = malloc(sizeof(cm_scache_t *) * cm_hashTableSize); - memset(cm_hashTablep, 0, sizeof(cm_scache_t *) * cm_hashTableSize); - cm_allFileLocks = NULL; - cm_currentSCaches = 0; - cm_maxSCaches = maxSCaches; - cm_fakeSCacheInit(); - cm_dnlcInit(); - osi_EndOnce(&once); - } + if (osi_Once(&once)) { + lock_InitializeRWLock(&cm_scacheLock, "cm_scacheLock"); + cm_hashTableSize = maxSCaches / 2; + cm_hashTablep = malloc(sizeof(cm_scache_t *) * cm_hashTableSize); + memset(cm_hashTablep, 0, sizeof(cm_scache_t *) * cm_hashTableSize); + cm_allFileLocks = NULL; + cm_currentSCaches = 0; + cm_maxSCaches = maxSCaches; + cm_fakeSCacheInit(); + cm_dnlcInit(); + osi_EndOnce(&once); + } } /* version that doesn't bother creating the entry if we don't find it */ cm_scache_t *cm_FindSCache(cm_fid_t *fidp) { - long hash; - cm_scache_t *scp; - - hash = CM_SCACHE_HASH(fidp); + long hash; + cm_scache_t *scp; + + hash = CM_SCACHE_HASH(fidp); - osi_assert(fidp->cell != 0); + osi_assert(fidp->cell != 0); - lock_ObtainWrite(&cm_scacheLock); - for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { - if (cm_FidCmp(fidp, &scp->fid) == 0) { - scp->refCount++; - cm_AdjustLRU(scp); - lock_ReleaseWrite(&cm_scacheLock); - return scp; - } + lock_ObtainWrite(&cm_scacheLock); + for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { + if (cm_FidCmp(fidp, &scp->fid) == 0) { + scp->refCount++; + cm_AdjustLRU(scp); + lock_ReleaseWrite(&cm_scacheLock); + return scp; } - lock_ReleaseWrite(&cm_scacheLock); - return NULL; + } + lock_ReleaseWrite(&cm_scacheLock); + return NULL; } long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, - cm_req_t *reqp) + cm_req_t *reqp) { - long hash; + long hash; cm_scache_t *scp; long code; cm_volume_t *volp = 0; cm_cell_t *cellp; char* mp = 0; - int special; // yj: boolean variable to test if file is on root.afs - int isRoot; + int special; // yj: boolean variable to test if file is on root.afs + int isRoot; extern cm_fid_t cm_rootFid; hash = CM_SCACHE_HASH(fidp); - osi_assert(fidp->cell != 0); + osi_assert(fidp->cell != 0); if (fidp->cell== cm_rootFid.cell && fidp->volume==cm_rootFid.volume && @@ -269,92 +269,92 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, osi_Log0(afsd_logp,"cm_getSCache called with root cell/volume and vnode=0 and unique=0"); } - // yj: check if we have the scp, if so, we don't need - // to do anything else + // yj: check if we have the scp, if so, we don't need + // to do anything else lock_ObtainWrite(&cm_scacheLock); - for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { - if (cm_FidCmp(fidp, &scp->fid) == 0) { - scp->refCount++; + for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { + if (cm_FidCmp(fidp, &scp->fid) == 0) { + scp->refCount++; *outScpp = scp; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); - return 0; + return 0; } } - // yj: when we get here, it means we don't have an scp - // so we need to either load it or fake it, depending - // on whether the file is "special", see below. - - // yj: if we're trying to get an scp for a file that's - // on root.afs of homecell, we want to handle it specially - // because we have to fill in the status stuff 'coz we - // don't want trybulkstat to fill it in for us + // yj: when we get here, it means we don't have an scp + // so we need to either load it or fake it, depending + // on whether the file is "special", see below. + + // yj: if we're trying to get an scp for a file that's + // on root.afs of homecell, we want to handle it specially + // because we have to fill in the status stuff 'coz we + // don't want trybulkstat to fill it in for us #ifdef AFS_FREELANCE_CLIENT - special = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && + special = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && - !(fidp->vnode==0x1 && fidp->unique==0x1)); - isRoot = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && + !(fidp->vnode==0x1 && fidp->unique==0x1)); + isRoot = (fidp->cell==AFS_FAKE_ROOT_CELL_ID && fidp->volume==AFS_FAKE_ROOT_VOL_ID && - fidp->vnode==0x1 && fidp->unique==0x1); - if (cm_freelanceEnabled && isRoot) { - osi_Log0(afsd_logp,"cm_getSCache Freelance and isRoot"); - /* freelance: if we are trying to get the root scp for the first + fidp->vnode==0x1 && fidp->unique==0x1); + if (cm_freelanceEnabled && isRoot) { + osi_Log0(afsd_logp,"cm_getSCache Freelance and isRoot"); + /* freelance: if we are trying to get the root scp for the first * time, we will just put in a place holder entry. */ - volp = NULL; - } + volp = NULL; + } - if (cm_freelanceEnabled && special) { - osi_Log0(afsd_logp,"cm_getSCache Freelance and special"); + if (cm_freelanceEnabled && special) { + osi_Log0(afsd_logp,"cm_getSCache Freelance and special"); if (fidp->vnode > 1) { lock_ObtainMutex(&cm_Freelance_Lock); - mp =(cm_localMountPoints+fidp->vnode-2)->mountPointStringp; - lock_ReleaseMutex(&cm_Freelance_Lock); + mp =(cm_localMountPoints+fidp->vnode-2)->mountPointStringp; + lock_ReleaseMutex(&cm_Freelance_Lock); } else { mp = ""; } - scp = cm_GetNewSCache(); + scp = cm_GetNewSCache(); - scp->fid = *fidp; - scp->volp = cm_rootSCachep->volp; - if (scp->dotdotFidp == (cm_fid_t *) NULL) - scp->dotdotFidp = (cm_fid_t *) malloc (sizeof(cm_fid_t)); - scp->dotdotFidp->cell=AFS_FAKE_ROOT_CELL_ID; - scp->dotdotFidp->volume=AFS_FAKE_ROOT_VOL_ID; - scp->dotdotFidp->unique=1; - scp->dotdotFidp->vnode=1; - scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); - scp->nextp=cm_hashTablep[hash]; - cm_hashTablep[hash]=scp; - scp->flags |= CM_SCACHEFLAG_INHASH; - scp->refCount = 1; - scp->fileType = CM_SCACHETYPE_MOUNTPOINT; - - lock_ObtainMutex(&cm_Freelance_Lock); - scp->length.LowPart = strlen(mp)+4; - scp->mountPointStringp=malloc(strlen(mp)+1); - strcpy(scp->mountPointStringp,mp); - lock_ReleaseMutex(&cm_Freelance_Lock); - - scp->owner=0x0; - scp->unixModeBits=0x1ff; - scp->clientModTime=FakeFreelanceModTime; - scp->serverModTime=FakeFreelanceModTime; - scp->parentUnique = 0x1; - scp->parentVnode=0x1; - scp->group=0; - scp->dataVersion=0x8; - *outScpp = scp; - lock_ReleaseWrite(&cm_scacheLock); - /*afsi_log(" getscache done");*/ - return 0; - } - // end of yj code + scp->fid = *fidp; + scp->volp = cm_rootSCachep->volp; + if (scp->dotdotFidp == (cm_fid_t *) NULL) + scp->dotdotFidp = (cm_fid_t *) malloc (sizeof(cm_fid_t)); + scp->dotdotFidp->cell=AFS_FAKE_ROOT_CELL_ID; + scp->dotdotFidp->volume=AFS_FAKE_ROOT_VOL_ID; + scp->dotdotFidp->unique=1; + scp->dotdotFidp->vnode=1; + scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); + scp->nextp=cm_hashTablep[hash]; + cm_hashTablep[hash]=scp; + scp->flags |= CM_SCACHEFLAG_INHASH; + scp->refCount = 1; + scp->fileType = (cm_localMountPoints+fidp->vnode-2)->fileType; + + lock_ObtainMutex(&cm_Freelance_Lock); + scp->length.LowPart = strlen(mp)+4; + scp->mountPointStringp=malloc(strlen(mp)+1); + strcpy(scp->mountPointStringp,mp); + lock_ReleaseMutex(&cm_Freelance_Lock); + + scp->owner=0x0; + scp->unixModeBits=0x1ff; + scp->clientModTime=FakeFreelanceModTime; + scp->serverModTime=FakeFreelanceModTime; + scp->parentUnique = 0x1; + scp->parentVnode=0x1; + scp->group=0; + scp->dataVersion=0x8; + *outScpp = scp; + lock_ReleaseWrite(&cm_scacheLock); + /*afsi_log(" getscache done");*/ + return 0; + } + // end of yj code #endif /* AFS_FREELANCE_CLIENT */ /* otherwise, we need to find the volume */ - if (!cm_freelanceEnabled || !isRoot) { + if (!cm_freelanceEnabled || !isRoot) { lock_ReleaseWrite(&cm_scacheLock); /* for perf. reasons */ cellp = cm_FindCellByID(fidp->cell); if (!cellp) @@ -364,56 +364,56 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, if (code) return code; lock_ObtainWrite(&cm_scacheLock); - } + } - /* otherwise, we have the volume, now reverify that the scp doesn't - * exist, and proceed. - */ - for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { - if (cm_FidCmp(fidp, &scp->fid) == 0) { - scp->refCount++; + /* otherwise, we have the volume, now reverify that the scp doesn't + * exist, and proceed. + */ + for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { + if (cm_FidCmp(fidp, &scp->fid) == 0) { + scp->refCount++; cm_AdjustLRU(scp); lock_ReleaseWrite(&cm_scacheLock); if (volp) - cm_PutVolume(volp); + cm_PutVolume(volp); *outScpp = scp; - return 0; + return 0; } } /* now, if we don't have the fid, recycle something */ - scp = cm_GetNewSCache(); - osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH)); - scp->fid = *fidp; - scp->volp = volp; /* a held reference */ - - if (!cm_freelanceEnabled || !isRoot) { - /* if this scache entry represents a volume root then we need - * to copy the dotdotFipd from the volume structure where the - * "master" copy is stored (defect 11489) - */ - if(scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) { + scp = cm_GetNewSCache(); + osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH)); + scp->fid = *fidp; + scp->volp = volp; /* a held reference */ + + if (!cm_freelanceEnabled || !isRoot) { + /* if this scache entry represents a volume root then we need + * to copy the dotdotFipd from the volume structure where the + * "master" copy is stored (defect 11489) + */ + if (scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) { if (scp->dotdotFidp == (cm_fid_t *) NULL) - scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t)); + scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t)); *(scp->dotdotFidp) = *volp->dotdotFidp; - } + } - if (volp->roID == fidp->volume) + if (volp->roID == fidp->volume) scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO); - else if (volp->bkID == fidp->volume) + else if (volp->bkID == fidp->volume) scp->flags |= CM_SCACHEFLAG_RO; - } - scp->nextp = cm_hashTablep[hash]; - cm_hashTablep[hash] = scp; + } + scp->nextp = cm_hashTablep[hash]; + cm_hashTablep[hash] = scp; scp->flags |= CM_SCACHEFLAG_INHASH; - scp->refCount = 1; - - /* XXX - The following fields in the cm_scache are - * uninitialized: - * fileType - * parentVnode - * parentUnique - */ + scp->refCount = 1; + + /* XXX - The following fields in the cm_scache are + * uninitialized: + * fileType + * parentVnode + * parentUnique + */ lock_ReleaseWrite(&cm_scacheLock); /* now we have a held scache entry; just return it */ @@ -477,278 +477,278 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp, * CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING. */ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp, - long rights, long flags) + long rights, long flags) { - osi_queueData_t *qdp; - long code; - cm_buf_t *tbufp; - long outRights; - int bufLocked; - - /* lookup this first */ - bufLocked = flags & CM_SCACHESYNC_BUFLOCKED; - - /* some minor assertions */ - if (flags & (CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_FETCHDATA - | CM_SCACHESYNC_READ | CM_SCACHESYNC_WRITE - | CM_SCACHESYNC_SETSIZE)) { - if (bufp) { - osi_assert(bufp->refCount > 0); - /* - osi_assert(cm_FidCmp(&bufp->fid, &scp->fid) == 0); - */ - } - } - else osi_assert(bufp == NULL); - - /* Do the access check. Now we don't really do the access check - * atomically, since the caller doesn't expect the parent dir to be - * returned locked, and that is what we'd have to do to prevent a - * callback breaking message on the parent due to a setacl call from - * being processed while we're running. So, instead, we check things - * here, and if things look fine with the access, we proceed to finish - * the rest of this check. Sort of a hack, but probably good enough. - */ + osi_queueData_t *qdp; + long code; + cm_buf_t *tbufp; + long outRights; + int bufLocked; + + /* lookup this first */ + bufLocked = flags & CM_SCACHESYNC_BUFLOCKED; + + /* some minor assertions */ + if (flags & (CM_SCACHESYNC_STOREDATA | CM_SCACHESYNC_FETCHDATA + | CM_SCACHESYNC_READ | CM_SCACHESYNC_WRITE + | CM_SCACHESYNC_SETSIZE)) { + if (bufp) { + osi_assert(bufp->refCount > 0); + /* + osi_assert(cm_FidCmp(&bufp->fid, &scp->fid) == 0); + */ + } + } + else osi_assert(bufp == NULL); + + /* Do the access check. Now we don't really do the access check + * atomically, since the caller doesn't expect the parent dir to be + * returned locked, and that is what we'd have to do to prevent a + * callback breaking message on the parent due to a setacl call from + * being processed while we're running. So, instead, we check things + * here, and if things look fine with the access, we proceed to finish + * the rest of this check. Sort of a hack, but probably good enough. + */ + + while (1) { + if (flags & CM_SCACHESYNC_FETCHSTATUS) { + /* if we're bringing in a new status block, ensure that + * we aren't already doing so, and that no one is + * changing the status concurrently, either. We need + * to do this, even if the status is of a different + * type, since we don't have the ability to figure out, + * in the AFS 3 protocols, which status-changing + * operation ran first, or even which order a read and + * a write occurred in. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) + goto sleep; + } + if (flags & (CM_SCACHESYNC_STORESIZE | CM_SCACHESYNC_STORESTATUS + | CM_SCACHESYNC_SETSIZE | CM_SCACHESYNC_GETCALLBACK)) { + /* if we're going to make an RPC to change the status, make sure + * that no one is bringing in or sending out the status. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) + goto sleep; + if (scp->bufReadsp || scp->bufWritesp) goto sleep; + } + if (flags & CM_SCACHESYNC_FETCHDATA) { + /* if we're bringing in a new chunk of data, make sure that + * nothing is happening to that chunk, and that we aren't + * changing the basic file status info, either. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) + goto sleep; + if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) + goto sleep; + } + if (flags & CM_SCACHESYNC_STOREDATA) { + /* same as fetch data */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) + goto sleep; + if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) + goto sleep; + } - while (1) { - if (flags & CM_SCACHESYNC_FETCHSTATUS) { - /* if we're bringing in a new status block, ensure that - * we aren't already doing so, and that no one is - * changing the status concurrently, either. We need - * to do this, even if the status is of a different - * type, since we don't have the ability to figure out, - * in the AFS 3 protocols, which status-changing - * operation ran first, or even which order a read and - * a write occurred in. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) - goto sleep; - } - if (flags & (CM_SCACHESYNC_STORESIZE | CM_SCACHESYNC_STORESTATUS - | CM_SCACHESYNC_SETSIZE | CM_SCACHESYNC_GETCALLBACK)) { - /* if we're going to make an RPC to change the status, make sure - * that no one is bringing in or sending out the status. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) - goto sleep; - if (scp->bufReadsp || scp->bufWritesp) goto sleep; - } - if (flags & CM_SCACHESYNC_FETCHDATA) { - /* if we're bringing in a new chunk of data, make sure that - * nothing is happening to that chunk, and that we aren't - * changing the basic file status info, either. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) - goto sleep; - if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) - goto sleep; - } - if (flags & CM_SCACHESYNC_STOREDATA) { - /* same as fetch data */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) - goto sleep; - if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) - goto sleep; - } + if (flags & CM_SCACHESYNC_STOREDATA_EXCL) { + /* Don't allow concurrent StoreData RPC's */ + if (scp->flags & CM_SCACHEFLAG_DATASTORING) + goto sleep; + } - if (flags & CM_SCACHESYNC_STOREDATA_EXCL) { - /* Don't allow concurrent StoreData RPC's */ - if (scp->flags & CM_SCACHEFLAG_DATASTORING) - goto sleep; - } - - if (flags & CM_SCACHESYNC_ASYNCSTORE) { - /* Don't allow more than one BKG store request */ - if (scp->flags & CM_SCACHEFLAG_ASYNCSTORING) - goto sleep; - } - - if (flags & CM_SCACHESYNC_LOCK) { - /* Don't allow concurrent fiddling with lock lists */ - if (scp->flags & CM_SCACHEFLAG_LOCKING) - goto sleep; - } - - /* now the operations that don't correspond to making RPCs */ - if (flags & CM_SCACHESYNC_GETSTATUS) { - /* we can use the status that's here, if we're not - * bringing in new status. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING)) - goto sleep; - } - if (flags & CM_SCACHESYNC_SETSTATUS) { - /* we can make a change to the local status, as long as - * the status isn't changing now. - * - * If we're fetching or storing a chunk of data, we can - * change the status locally, since the fetch/store - * operations don't change any of the data that we're - * changing here. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING)) - goto sleep; - } - if (flags & CM_SCACHESYNC_READ) { - /* we're going to read the data, make sure that the - * status is available, and that the data is here. It - * is OK to read while storing the data back. - */ - if (scp->flags & CM_SCACHEFLAG_FETCHING) - goto sleep; - if (bufp && ((bufp->cmFlags - & (CM_BUF_CMFETCHING - | CM_BUF_CMFULLYFETCHED)) - == CM_BUF_CMFETCHING)) - goto sleep; - } - if (flags & CM_SCACHESYNC_WRITE) { - /* don't write unless the status is stable and the chunk - * is stable. - */ - if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING - | CM_SCACHEFLAG_SIZESTORING)) - goto sleep; - if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) - goto sleep; - } + if (flags & CM_SCACHESYNC_ASYNCSTORE) { + /* Don't allow more than one BKG store request */ + if (scp->flags & CM_SCACHEFLAG_ASYNCSTORING) + goto sleep; + } + + if (flags & CM_SCACHESYNC_LOCK) { + /* Don't allow concurrent fiddling with lock lists */ + if (scp->flags & CM_SCACHEFLAG_LOCKING) + goto sleep; + } - // yj: modified this so that callback only checked if we're - // not checking something on /afs + /* now the operations that don't correspond to making RPCs */ + if (flags & CM_SCACHESYNC_GETSTATUS) { + /* we can use the status that's here, if we're not + * bringing in new status. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING)) + goto sleep; + } + if (flags & CM_SCACHESYNC_SETSTATUS) { + /* we can make a change to the local status, as long as + * the status isn't changing now. + * + * If we're fetching or storing a chunk of data, we can + * change the status locally, since the fetch/store + * operations don't change any of the data that we're + * changing here. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING)) + goto sleep; + } + if (flags & CM_SCACHESYNC_READ) { + /* we're going to read the data, make sure that the + * status is available, and that the data is here. It + * is OK to read while storing the data back. + */ + if (scp->flags & CM_SCACHEFLAG_FETCHING) + goto sleep; + if (bufp && ((bufp->cmFlags + & (CM_BUF_CMFETCHING + | CM_BUF_CMFULLYFETCHED)) + == CM_BUF_CMFETCHING)) + goto sleep; + } + if (flags & CM_SCACHESYNC_WRITE) { + /* don't write unless the status is stable and the chunk + * is stable. + */ + if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING + | CM_SCACHEFLAG_SIZESTORING)) + goto sleep; + if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) + goto sleep; + } + + // yj: modified this so that callback only checked if we're + // not checking something on /afs /* fix the conditional to match the one in cm_HaveCallback */ - if ( (flags & CM_SCACHESYNC_NEEDCALLBACK) + if ( (flags & CM_SCACHESYNC_NEEDCALLBACK) #ifdef AFS_FREELANCE_CLIENT && (!cm_freelanceEnabled || !(scp->fid.vnode==0x1 && scp->fid.unique==0x1) || scp->fid.cell!=AFS_FAKE_ROOT_CELL_ID || scp->fid.volume!=AFS_FAKE_ROOT_VOL_ID || - cm_fakeDirCallback < 2) + cm_fakeDirCallback < 2) #endif /* AFS_FREELANCE_CLIENT */ - ) { - if (!cm_HaveCallback(scp)) { - osi_Log1(afsd_logp, "CM SyncOp getting callback on scp %x", - (long) scp); - if (bufLocked) lock_ReleaseMutex(&bufp->mx); - code = cm_GetCallback(scp, up, reqp, 0); - if (bufLocked) { - lock_ReleaseMutex(&scp->mx); - lock_ObtainMutex(&bufp->mx); - lock_ObtainMutex(&scp->mx); - } - if (code) return code; - continue; - } + ) { + if (!cm_HaveCallback(scp)) { + osi_Log1(afsd_logp, "CM SyncOp getting callback on scp %x", + (long) scp); + if (bufLocked) lock_ReleaseMutex(&bufp->mx); + code = cm_GetCallback(scp, up, reqp, 0); + if (bufLocked) { + lock_ReleaseMutex(&scp->mx); + lock_ObtainMutex(&bufp->mx); + lock_ObtainMutex(&scp->mx); } - - if (rights) { - /* can't check access rights without a callback */ - osi_assert(flags & CM_SCACHESYNC_NEEDCALLBACK); - - if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO)) - return CM_ERROR_READONLY; - - if (cm_HaveAccessRights(scp, up, rights, &outRights)) { - if (~outRights & rights) return CM_ERROR_NOACCESS; - } - else { - /* we don't know the required access rights */ - if (bufLocked) lock_ReleaseMutex(&bufp->mx); - code = cm_GetAccessRights(scp, up, reqp); - if (code) return code; - if (bufLocked) { - lock_ReleaseMutex(&scp->mx); - lock_ObtainMutex(&bufp->mx); - lock_ObtainMutex(&scp->mx); - } - continue; - } + if (code) return code; + continue; + } + } + + if (rights) { + /* can't check access rights without a callback */ + osi_assert(flags & CM_SCACHESYNC_NEEDCALLBACK); + + if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO)) + return CM_ERROR_READONLY; + + if (cm_HaveAccessRights(scp, up, rights, &outRights)) { + if (~outRights & rights) return CM_ERROR_NOACCESS; + } + else { + /* we don't know the required access rights */ + if (bufLocked) lock_ReleaseMutex(&bufp->mx); + code = cm_GetAccessRights(scp, up, reqp); + if (code) return code; + if (bufLocked) { + lock_ReleaseMutex(&scp->mx); + lock_ObtainMutex(&bufp->mx); + lock_ObtainMutex(&scp->mx); } + continue; + } + } - /* if we get here, we're happy */ - break; + /* if we get here, we're happy */ + break; -sleep: - /* first check if we're not supposed to wait: fail - * in this case, returning with everything still locked. - */ - if (flags & CM_SCACHESYNC_NOWAIT) return CM_ERROR_WOULDBLOCK; + sleep: + /* first check if we're not supposed to wait: fail + * in this case, returning with everything still locked. + */ + if (flags & CM_SCACHESYNC_NOWAIT) return CM_ERROR_WOULDBLOCK; - /* wait here, then try again */ - osi_Log1(afsd_logp, "CM SyncOp sleeping scp %x", (long) scp); + /* wait here, then try again */ + osi_Log1(afsd_logp, "CM SyncOp sleeping scp %x", (long) scp); if ( scp->flags & CM_SCACHEFLAG_WAITING ) osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING already set for 0x%x", scp); else osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING set for 0x%x", scp); - scp->flags |= CM_SCACHEFLAG_WAITING; - if (bufLocked) lock_ReleaseMutex(&bufp->mx); + scp->flags |= CM_SCACHEFLAG_WAITING; + if (bufLocked) lock_ReleaseMutex(&bufp->mx); osi_SleepM((long) &scp->flags, &scp->mx); osi_Log0(afsd_logp, "CM SyncOp woke!"); if (bufLocked) lock_ObtainMutex(&bufp->mx); lock_ObtainMutex(&scp->mx); - } /* big while loop */ + } /* big while loop */ - /* now, update the recorded state for RPC-type calls */ - if (flags & CM_SCACHESYNC_FETCHSTATUS) - scp->flags |= CM_SCACHEFLAG_FETCHING; - if (flags & CM_SCACHESYNC_STORESTATUS) - scp->flags |= CM_SCACHEFLAG_STORING; - if (flags & CM_SCACHESYNC_STORESIZE) - scp->flags |= CM_SCACHEFLAG_SIZESTORING; - if (flags & CM_SCACHESYNC_GETCALLBACK) - scp->flags |= CM_SCACHEFLAG_GETCALLBACK; - if (flags & CM_SCACHESYNC_STOREDATA_EXCL) - scp->flags |= CM_SCACHEFLAG_DATASTORING; - if (flags & CM_SCACHESYNC_ASYNCSTORE) - scp->flags |= CM_SCACHEFLAG_ASYNCSTORING; - if (flags & CM_SCACHESYNC_LOCK) - scp->flags |= CM_SCACHEFLAG_LOCKING; - - /* now update the buffer pointer */ - if (flags & CM_SCACHESYNC_FETCHDATA) { - /* ensure that the buffer isn't already in the I/O list */ - if (bufp) { - for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { - tbufp = osi_GetQData(qdp); - osi_assert(tbufp != bufp); - } - } - - /* queue a held reference to the buffer in the "reading" I/O list */ - qdp = osi_QDAlloc(); - osi_SetQData(qdp, bufp); - if (bufp) { - buf_Hold(bufp); - bufp->cmFlags |= CM_BUF_CMFETCHING; - } - osi_QAdd((osi_queue_t **) &scp->bufReadsp, &qdp->q); + /* now, update the recorded state for RPC-type calls */ + if (flags & CM_SCACHESYNC_FETCHSTATUS) + scp->flags |= CM_SCACHEFLAG_FETCHING; + if (flags & CM_SCACHESYNC_STORESTATUS) + scp->flags |= CM_SCACHEFLAG_STORING; + if (flags & CM_SCACHESYNC_STORESIZE) + scp->flags |= CM_SCACHEFLAG_SIZESTORING; + if (flags & CM_SCACHESYNC_GETCALLBACK) + scp->flags |= CM_SCACHEFLAG_GETCALLBACK; + if (flags & CM_SCACHESYNC_STOREDATA_EXCL) + scp->flags |= CM_SCACHEFLAG_DATASTORING; + if (flags & CM_SCACHESYNC_ASYNCSTORE) + scp->flags |= CM_SCACHEFLAG_ASYNCSTORING; + if (flags & CM_SCACHESYNC_LOCK) + scp->flags |= CM_SCACHEFLAG_LOCKING; + + /* now update the buffer pointer */ + if (flags & CM_SCACHESYNC_FETCHDATA) { + /* ensure that the buffer isn't already in the I/O list */ + if (bufp) { + for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { + tbufp = osi_GetQData(qdp); + osi_assert(tbufp != bufp); + } } - if (flags & CM_SCACHESYNC_STOREDATA) { - /* ensure that the buffer isn't already in the I/O list */ - if (bufp) { - for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { - tbufp = osi_GetQData(qdp); - osi_assert(tbufp != bufp); - } - } - - /* queue a held reference to the buffer in the "writing" I/O list */ - qdp = osi_QDAlloc(); - osi_SetQData(qdp, bufp); - if (bufp) { - buf_Hold(bufp); - bufp->cmFlags |= CM_BUF_CMSTORING; - } - osi_QAdd((osi_queue_t **) &scp->bufWritesp, &qdp->q); + /* queue a held reference to the buffer in the "reading" I/O list */ + qdp = osi_QDAlloc(); + osi_SetQData(qdp, bufp); + if (bufp) { + buf_Hold(bufp); + bufp->cmFlags |= CM_BUF_CMFETCHING; } - - return 0; + osi_QAdd((osi_queue_t **) &scp->bufReadsp, &qdp->q); + } + + if (flags & CM_SCACHESYNC_STOREDATA) { + /* ensure that the buffer isn't already in the I/O list */ + if (bufp) { + for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { + tbufp = osi_GetQData(qdp); + osi_assert(tbufp != bufp); + } + } + + /* queue a held reference to the buffer in the "writing" I/O list */ + qdp = osi_QDAlloc(); + osi_SetQData(qdp, bufp); + if (bufp) { + buf_Hold(bufp); + bufp->cmFlags |= CM_BUF_CMSTORING; + } + osi_QAdd((osi_queue_t **) &scp->bufWritesp, &qdp->q); + } + + return 0; } /* for those syncops that setup for RPCs. @@ -756,67 +756,67 @@ sleep: */ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags) { - osi_queueData_t *qdp; - cm_buf_t *tbufp; - - /* now, update the recorded state for RPC-type calls */ - if (flags & CM_SCACHESYNC_FETCHSTATUS) - scp->flags &= ~CM_SCACHEFLAG_FETCHING; - if (flags & CM_SCACHESYNC_STORESTATUS) - scp->flags &= ~CM_SCACHEFLAG_STORING; - if (flags & CM_SCACHESYNC_STORESIZE) - scp->flags &= ~CM_SCACHEFLAG_SIZESTORING; - if (flags & CM_SCACHESYNC_GETCALLBACK) - scp->flags &= ~CM_SCACHEFLAG_GETCALLBACK; - if (flags & CM_SCACHESYNC_STOREDATA_EXCL) - scp->flags &= ~CM_SCACHEFLAG_DATASTORING; - if (flags & CM_SCACHESYNC_ASYNCSTORE) - scp->flags &= ~CM_SCACHEFLAG_ASYNCSTORING; - if (flags & CM_SCACHESYNC_LOCK) - scp->flags &= ~CM_SCACHEFLAG_LOCKING; - - /* now update the buffer pointer */ - if (flags & CM_SCACHESYNC_FETCHDATA) { - /* ensure that the buffer isn't already in the I/O list */ - for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { - tbufp = osi_GetQData(qdp); - if (tbufp == bufp) break; - } - osi_assert(qdp != NULL); - osi_assert(osi_GetQData(qdp) == bufp); - osi_QRemove((osi_queue_t **) &scp->bufReadsp, &qdp->q); - osi_QDFree(qdp); - if (bufp) { - bufp->cmFlags &= - ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED); - buf_Release(bufp); - } + osi_queueData_t *qdp; + cm_buf_t *tbufp; + + /* now, update the recorded state for RPC-type calls */ + if (flags & CM_SCACHESYNC_FETCHSTATUS) + scp->flags &= ~CM_SCACHEFLAG_FETCHING; + if (flags & CM_SCACHESYNC_STORESTATUS) + scp->flags &= ~CM_SCACHEFLAG_STORING; + if (flags & CM_SCACHESYNC_STORESIZE) + scp->flags &= ~CM_SCACHEFLAG_SIZESTORING; + if (flags & CM_SCACHESYNC_GETCALLBACK) + scp->flags &= ~CM_SCACHEFLAG_GETCALLBACK; + if (flags & CM_SCACHESYNC_STOREDATA_EXCL) + scp->flags &= ~CM_SCACHEFLAG_DATASTORING; + if (flags & CM_SCACHESYNC_ASYNCSTORE) + scp->flags &= ~CM_SCACHEFLAG_ASYNCSTORING; + if (flags & CM_SCACHESYNC_LOCK) + scp->flags &= ~CM_SCACHEFLAG_LOCKING; + + /* now update the buffer pointer */ + if (flags & CM_SCACHESYNC_FETCHDATA) { + /* ensure that the buffer isn't already in the I/O list */ + for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { + tbufp = osi_GetQData(qdp); + if (tbufp == bufp) break; + } + osi_assert(qdp != NULL); + osi_assert(osi_GetQData(qdp) == bufp); + osi_QRemove((osi_queue_t **) &scp->bufReadsp, &qdp->q); + osi_QDFree(qdp); + if (bufp) { + bufp->cmFlags &= + ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED); + buf_Release(bufp); } + } - /* now update the buffer pointer */ - if (flags & CM_SCACHESYNC_STOREDATA) { - /* ensure that the buffer isn't already in the I/O list */ - for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { - tbufp = osi_GetQData(qdp); - if (tbufp == bufp) break; - } - osi_assert(qdp != NULL); - osi_assert(osi_GetQData(qdp) == bufp); - osi_QRemove((osi_queue_t **) &scp->bufWritesp, &qdp->q); - osi_QDFree(qdp); - if (bufp) { - bufp->cmFlags &= ~CM_BUF_CMSTORING; - buf_Release(bufp); - } + /* now update the buffer pointer */ + if (flags & CM_SCACHESYNC_STOREDATA) { + /* ensure that the buffer isn't already in the I/O list */ + for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { + tbufp = osi_GetQData(qdp); + if (tbufp == bufp) break; } - - /* and wakeup anyone who is waiting */ - if (scp->flags & CM_SCACHEFLAG_WAITING) { - osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING reset for 0x%x", scp); - scp->flags &= ~CM_SCACHEFLAG_WAITING; - osi_Wakeup((long) &scp->flags); + osi_assert(qdp != NULL); + osi_assert(osi_GetQData(qdp) == bufp); + osi_QRemove((osi_queue_t **) &scp->bufWritesp, &qdp->q); + osi_QDFree(qdp); + if (bufp) { + bufp->cmFlags &= ~CM_BUF_CMSTORING; + buf_Release(bufp); } -} + } + + /* and wakeup anyone who is waiting */ + if (scp->flags & CM_SCACHEFLAG_WAITING) { + osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING reset for 0x%x", scp); + scp->flags &= ~CM_SCACHEFLAG_WAITING; + osi_Wakeup((long) &scp->flags); + } +} /* merge in a response from an RPC. The scp must be locked, and the callback * is optional. @@ -832,123 +832,123 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags) * started before that, can cause old info to be merged from the first call. */ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp, - cm_user_t *userp, int flags) + cm_user_t *userp, int flags) { - // yj: i want to create some fake status for the /afs directory and the - // entries under that directory + // yj: i want to create some fake status for the /afs directory and the + // entries under that directory #ifdef AFS_FREELANCE_CLIENT - if (cm_freelanceEnabled && scp == cm_rootSCachep) { - osi_Log0(afsd_logp,"cm_MergeStatus Freelance cm_rootSCachep"); - statusp->InterfaceVersion = 0x1; + if (cm_freelanceEnabled && scp == cm_rootSCachep) { + osi_Log0(afsd_logp,"cm_MergeStatus Freelance cm_rootSCachep"); + statusp->InterfaceVersion = 0x1; statusp->FileType = CM_SCACHETYPE_DIRECTORY; - statusp->LinkCount = scp->linkCount; - statusp->Length = cm_fakeDirSize; - statusp->DataVersion = cm_fakeDirVersion; - statusp->Author = 0x1; - statusp->Owner = 0x0; - statusp->CallerAccess = 0x9; - statusp->AnonymousAccess = 0x9; - statusp->UnixModeBits = 0x1ff; - statusp->ParentVnode = 0x1; - statusp->ParentUnique = 0x1; - statusp->ResidencyMask = 0; - statusp->ClientModTime = FakeFreelanceModTime; - statusp->ServerModTime = FakeFreelanceModTime; - statusp->Group = 0; - statusp->SyncCounter = 0; - statusp->dataVersionHigh = 0; - } + statusp->LinkCount = scp->linkCount; + statusp->Length = cm_fakeDirSize; + statusp->DataVersion = cm_fakeDirVersion; + statusp->Author = 0x1; + statusp->Owner = 0x0; + statusp->CallerAccess = 0x9; + statusp->AnonymousAccess = 0x9; + statusp->UnixModeBits = 0x1ff; + statusp->ParentVnode = 0x1; + statusp->ParentUnique = 0x1; + statusp->ResidencyMask = 0; + statusp->ClientModTime = FakeFreelanceModTime; + statusp->ServerModTime = FakeFreelanceModTime; + statusp->Group = 0; + statusp->SyncCounter = 0; + statusp->dataVersionHigh = 0; + } #endif /* AFS_FREELANCE_CLIENT */ - if (!(flags & CM_MERGEFLAG_FORCE) - && statusp->DataVersion < (unsigned long) scp->dataVersion) { - struct cm_cell *cellp; - struct cm_volume *volp; - - cellp = cm_FindCellByID(scp->fid.cell); - cm_GetVolumeByID(cellp, scp->fid.volume, userp, - (cm_req_t *) NULL, &volp); - if (scp->cbServerp) - osi_Log2(afsd_logp, "old data from server %x volume %s", - scp->cbServerp->addr.sin_addr.s_addr, - volp->namep); - osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d", - scp, scp->dataVersion, statusp->DataVersion); - /* we have a number of data fetch/store operations running - * concurrently, and we can tell which one executed last at the - * server by its mtime. - * Choose the one with the largest mtime, and ignore the rest. - * - * These concurrent calls are incompatible with setting the - * mtime, so we won't have a locally changed mtime here. - * - * We could also have ACL info for a different user than usual, - * in which case we have to do that part of the merge, anyway. - * We won't have to worry about the info being old, since we - * won't have concurrent calls - * that change file status running from this machine. - * - * Added 3/17/98: if we see data version regression on an RO - * file, it's probably due to a server holding an out-of-date - * replica, rather than to concurrent RPC's. Failures to - * release replicas are now flagged by the volserver, but only - * since AFS 3.4 5.22, so there are plenty of clients getting - * out-of-date replicas out there. - * - * If we discover an out-of-date replica, by this time it's too - * late to go to another server and retry. Also, we can't - * reject the merge, because then there is no way for - * GetAccess to do its work, and the caller gets into an - * infinite loop. So we just grin and bear it. - */ - if (!(scp->flags & CM_SCACHEFLAG_RO)) - return; - } - scp->serverModTime = statusp->ServerModTime; - - if (!(scp->mask & CM_SCACHEMASK_CLIENTMODTIME)) { - scp->clientModTime = statusp->ClientModTime; - } - if (!(scp->mask & CM_SCACHEMASK_LENGTH)) { - scp->length.LowPart = statusp->Length; - scp->length.HighPart = 0; - } - - scp->serverLength.LowPart = statusp->Length; - scp->serverLength.HighPart = 0; - - scp->linkCount = statusp->LinkCount; - scp->dataVersion = statusp->DataVersion; - scp->owner = statusp->Owner; - scp->group = statusp->Group; - scp->unixModeBits = statusp->UnixModeBits & 07777; - - if (statusp->FileType == File) - scp->fileType = CM_SCACHETYPE_FILE; - else if (statusp->FileType == Directory) - scp->fileType = CM_SCACHETYPE_DIRECTORY; - else if (statusp->FileType == SymbolicLink) { - if ((scp->unixModeBits & 0111) == 0) - scp->fileType = CM_SCACHETYPE_MOUNTPOINT; - else - scp->fileType = CM_SCACHETYPE_SYMLINK; - } + if (!(flags & CM_MERGEFLAG_FORCE) + && statusp->DataVersion < (unsigned long) scp->dataVersion) { + struct cm_cell *cellp; + struct cm_volume *volp; + + cellp = cm_FindCellByID(scp->fid.cell); + cm_GetVolumeByID(cellp, scp->fid.volume, userp, + (cm_req_t *) NULL, &volp); + if (scp->cbServerp) + osi_Log2(afsd_logp, "old data from server %x volume %s", + scp->cbServerp->addr.sin_addr.s_addr, + volp->namep); + osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d", + scp, scp->dataVersion, statusp->DataVersion); + /* we have a number of data fetch/store operations running + * concurrently, and we can tell which one executed last at the + * server by its mtime. + * Choose the one with the largest mtime, and ignore the rest. + * + * These concurrent calls are incompatible with setting the + * mtime, so we won't have a locally changed mtime here. + * + * We could also have ACL info for a different user than usual, + * in which case we have to do that part of the merge, anyway. + * We won't have to worry about the info being old, since we + * won't have concurrent calls + * that change file status running from this machine. + * + * Added 3/17/98: if we see data version regression on an RO + * file, it's probably due to a server holding an out-of-date + * replica, rather than to concurrent RPC's. Failures to + * release replicas are now flagged by the volserver, but only + * since AFS 3.4 5.22, so there are plenty of clients getting + * out-of-date replicas out there. + * + * If we discover an out-of-date replica, by this time it's too + * late to go to another server and retry. Also, we can't + * reject the merge, because then there is no way for + * GetAccess to do its work, and the caller gets into an + * infinite loop. So we just grin and bear it. + */ + if (!(scp->flags & CM_SCACHEFLAG_RO)) + return; + } + scp->serverModTime = statusp->ServerModTime; + + if (!(scp->mask & CM_SCACHEMASK_CLIENTMODTIME)) { + scp->clientModTime = statusp->ClientModTime; + } + if (!(scp->mask & CM_SCACHEMASK_LENGTH)) { + scp->length.LowPart = statusp->Length; + scp->length.HighPart = 0; + } + + scp->serverLength.LowPart = statusp->Length; + scp->serverLength.HighPart = 0; + + scp->linkCount = statusp->LinkCount; + scp->dataVersion = statusp->DataVersion; + scp->owner = statusp->Owner; + scp->group = statusp->Group; + scp->unixModeBits = statusp->UnixModeBits & 07777; + + if (statusp->FileType == File) + scp->fileType = CM_SCACHETYPE_FILE; + else if (statusp->FileType == Directory) + scp->fileType = CM_SCACHETYPE_DIRECTORY; + else if (statusp->FileType == SymbolicLink) { + if ((scp->unixModeBits & 0111) == 0) + scp->fileType = CM_SCACHETYPE_MOUNTPOINT; + else + scp->fileType = CM_SCACHETYPE_SYMLINK; + } else { osi_Log1(afsd_logp, "Merge, Invalid File Type, scp %x", scp); scp->fileType = 0; /* invalid */ } - /* and other stuff */ - scp->parentVnode = statusp->ParentVnode; - scp->parentUnique = statusp->ParentUnique; + /* and other stuff */ + scp->parentVnode = statusp->ParentVnode; + scp->parentUnique = statusp->ParentUnique; - /* and merge in the private acl cache info, if this is more than the public - * info; merge in the public stuff in any case. - */ - scp->anyAccess = statusp->AnonymousAccess; + /* and merge in the private acl cache info, if this is more than the public + * info; merge in the public stuff in any case. + */ + scp->anyAccess = statusp->AnonymousAccess; - if (userp != NULL) { - cm_AddACLCache(scp, userp, statusp->CallerAccess); - } + if (userp != NULL) { + cm_AddACLCache(scp, userp, statusp->CallerAccess); + } } /* note that our stat cache info is incorrect, so force us eventually @@ -961,60 +961,58 @@ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp, */ void cm_DiscardSCache(cm_scache_t *scp) { - lock_AssertMutex(&scp->mx); + lock_AssertMutex(&scp->mx); if (scp->cbServerp) { cm_PutServer(scp->cbServerp); scp->cbServerp = NULL; } - scp->cbExpires = 0; - cm_dnlcPurgedp(scp); - cm_FreeAllACLEnts(scp); + scp->cbExpires = 0; + cm_dnlcPurgedp(scp); + cm_FreeAllACLEnts(scp); } void cm_AFSFidFromFid(AFSFid *afsFidp, cm_fid_t *fidp) { - afsFidp->Volume = fidp->volume; - afsFidp->Vnode = fidp->vnode; - afsFidp->Unique = fidp->unique; -} + afsFidp->Volume = fidp->volume; + afsFidp->Vnode = fidp->vnode; + afsFidp->Unique = fidp->unique; +} void cm_HoldSCache(cm_scache_t *scp) { - lock_ObtainWrite(&cm_scacheLock); - osi_assert(scp->refCount > 0); - scp->refCount++; - lock_ReleaseWrite(&cm_scacheLock); + lock_ObtainWrite(&cm_scacheLock); + osi_assert(scp->refCount > 0); + scp->refCount++; + lock_ReleaseWrite(&cm_scacheLock); } void cm_ReleaseSCache(cm_scache_t *scp) { - lock_ObtainWrite(&cm_scacheLock); - osi_assert(scp->refCount-- > 0); - lock_ReleaseWrite(&cm_scacheLock); + lock_ObtainWrite(&cm_scacheLock); + osi_assert(scp->refCount-- > 0); + lock_ReleaseWrite(&cm_scacheLock); } /* just look for the scp entry to get filetype */ /* doesn't need to be perfectly accurate, so locking doesn't matter too much */ int cm_FindFileType(cm_fid_t *fidp) { - long hash; - cm_scache_t *scp; + long hash; + cm_scache_t *scp; - hash = CM_SCACHE_HASH(fidp); + hash = CM_SCACHE_HASH(fidp); - osi_assert(fidp->cell != 0); + osi_assert(fidp->cell != 0); - lock_ObtainWrite(&cm_scacheLock); - for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { - if (cm_FidCmp(fidp, &scp->fid) == 0) { - /*scp->refCount++;*/ - /*cm_AdjustLRU(scp);*/ - lock_ReleaseWrite(&cm_scacheLock); - return scp->fileType; - } + lock_ObtainWrite(&cm_scacheLock); + for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) { + if (cm_FidCmp(fidp, &scp->fid) == 0) { + lock_ReleaseWrite(&cm_scacheLock); + return scp->fileType; } - lock_ReleaseWrite(&cm_scacheLock); - return 0; + } + lock_ReleaseWrite(&cm_scacheLock); + return 0; } /* dump all scp's that have reference count > 0 to a file. diff --git a/src/WINNT/afsd/cm_scache.h b/src/WINNT/afsd/cm_scache.h index 18b345033..3cf2bf33c 100644 --- a/src/WINNT/afsd/cm_scache.h +++ b/src/WINNT/afsd/cm_scache.h @@ -24,7 +24,7 @@ typedef struct cm_fid { typedef struct cm_accessCache { osi_queue_t q; /* queue header */ struct cm_user *userp; /* user having access rights */ - long rights; /* rights */ + unsigned long rights; /* rights */ } cm_accessCache_t; typedef struct cm_file_lock { @@ -50,7 +50,7 @@ typedef struct cm_scache { osi_queue_t q; /* lru queue; cm_scacheLock */ struct cm_scache *nextp; /* next in hash; cm_scacheLock */ cm_fid_t fid; - long flags; /* flags; locked by mx */ + unsigned long flags; /* flags; locked by mx */ /* synchronization stuff */ osi_mutex_t mx; /* mutex for this structure */ @@ -67,17 +67,17 @@ typedef struct cm_scache { long parentUnique; /* for ACL callbacks */ /* local modification stat */ - long mask; /* for clientModTime, length and + unsigned long mask; /* for clientModTime, length and * truncPos */ /* file status */ - int fileType; /* file type */ + unsigned int fileType; /* file type */ time_t clientModTime; /* mtime */ time_t serverModTime; /* at server, for concurrent call * comparisons */ osi_hyper_t length; /* file length */ cm_prefetch_t prefetch; /* prefetch info structure */ - int unixModeBits; /* unix protection mode bits */ + unsigned int unixModeBits; /* unix protection mode bits */ int linkCount; /* link count */ long dataVersion; /* data version */ long owner; /* file owner */ @@ -118,7 +118,7 @@ typedef struct cm_scache { osi_hyper_t bulkStatProgress; /* track bulk stats of large dirs */ /* open state */ - short openReads; /* opens for reading */ + short openReads; /* open for reading */ short openWrites; /* open for writing */ short openShares; /* open for read excl */ short openExcls; /* open for exclusives */ diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 17511447f..e14de57b2 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -427,6 +427,9 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp, * Iterate through all entries in a directory. * When the function funcp is called, the buffer is locked but the * directory vnode is not. + * + * If the retscp parameter is not NULL, the parmp must be a + * cm_lookupSearch_t object. */ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp, osi_hyper_t *startOffsetp, cm_user_t *userp, cm_req_t *reqp, @@ -465,17 +468,26 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp, if (retscp) /* if this is a lookup call */ { cm_lookupSearch_t* sp = parmp; - int casefold = sp->caseFold; - - sp->caseFold = 0; /* we have a strong preference for exact matches */ - if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */ - { - sp->caseFold = casefold; - lock_ReleaseMutex(&scp->mx); - return 0; - } - sp->caseFold = casefold; +#ifdef AFS_FREELANCE_CLIENT + /* Freelance entries never end up in the DNLC because they + * do not have an associated cm_server_t + */ + if ( !(cm_freelanceEnabled && + sp->fid.cell==AFS_FAKE_ROOT_CELL_ID && + sp->fid.volume==AFS_FAKE_ROOT_VOL_ID ) ) +#endif /* AFS_FREELANCE_CLIENT */ + { + int casefold = sp->caseFold; + sp->caseFold = 0; /* we have a strong preference for exact matches */ + if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */ + { + sp->caseFold = casefold; + lock_ReleaseMutex(&scp->mx); + return 0; + } + sp->caseFold = casefold; + } } /* @@ -787,7 +799,8 @@ long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) } } /* locked, has callback, has valid data in buffer */ - if ((tlen = scp->length.LowPart) > 1000) return CM_ERROR_TOOBIG; + if ((tlen = scp->length.LowPart) > 1000) + return CM_ERROR_TOOBIG; if (tlen <= 0) { code = CM_ERROR_INVAL; goto done; @@ -1096,6 +1109,13 @@ long cm_Lookup(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp, int sysNameIndex = 0; cm_scache_t *scp = 0; + if ( stricmp(namep,SMB_IOCTL_FILENAME_NOSLASH) == 0 ) { + if (flags & CM_FLAG_CHECKPATH) + return CM_ERROR_NOSUCHPATH; + else + return CM_ERROR_NOSUCHFILE; + } + for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) { code = cm_ExpandSysName(namep, tname, sizeof(tname), sysNameIndex); if (code > 0) { @@ -1104,10 +1124,10 @@ long cm_Lookup(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp, *outpScpp = scp; return 0; } - if (scp) { - cm_ReleaseSCache(scp); - scp = 0; - } + if (scp) { + cm_ReleaseSCache(scp); + scp = 0; + } } else { return cm_LookupInternal(dscp, namep, flags, userp, reqp, outpScpp); } @@ -1405,12 +1425,12 @@ long cm_NameI(cm_scache_t *rootSCachep, char *pathp, long flags, if (tscp->fileType == CM_SCACHETYPE_SYMLINK) { /* this is a symlink; assemble a new buffer */ lock_ReleaseMutex(&tscp->mx); - if (symlinkCount++ >= 16) { + if (symlinkCount++ >= MAX_SYMLINK_COUNT) { cm_ReleaseSCache(tscp); cm_ReleaseSCache(dirScp); if (psp) cm_FreeSpace(psp); - return CM_ERROR_TOOBIG; + return CM_ERROR_TOO_MANY_SYMLINKS; } if (tc == 0) restp = ""; @@ -1659,9 +1679,10 @@ void cm_TryBulkStat(cm_scache_t *dscp, osi_hyper_t *offsetp, cm_user_t *userp, bb.counter = 0; bb.bufOffset = *offsetp; + lock_ReleaseMutex(&dscp->mx); /* first, assemble the file IDs we need to stat */ - code = cm_ApplyDir(dscp, cm_TryBulkProc, (void *) &bb, offsetp, userp, - reqp, NULL); + code = cm_ApplyDir(dscp, cm_TryBulkProc, (void *) &bb, offsetp, userp, reqp, NULL); + lock_ObtainMutex(&dscp->mx); /* if we failed, bail out early */ if (code && code != CM_ERROR_STOPNOW) return; @@ -1671,7 +1692,7 @@ void cm_TryBulkStat(cm_scache_t *dscp, osi_hyper_t *offsetp, cm_user_t *userp, * time. */ filex = 0; - while(filex < bb.counter) { + while (filex < bb.counter) { filesThisCall = bb.counter - filex; if (filesThisCall > AFSCBMAX) filesThisCall = AFSCBMAX; diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index 9f2a7a641..fc5a5e57c 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -154,4 +154,5 @@ extern void cm_CheckLocks(); extern long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead); +#define MAX_SYMLINK_COUNT 16 #endif /* __CM_VNODEOPS_H_ENV__ */ diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index fb3e1aefd..ebea271a7 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -387,10 +387,21 @@ unsigned int smb_Attributes(cm_scache_t *scp) { unsigned int attrs; - if (scp->fileType == CM_SCACHETYPE_DIRECTORY - || scp->fileType == CM_SCACHETYPE_MOUNTPOINT) + if ( scp->fileType == CM_SCACHETYPE_DIRECTORY || + scp->fileType == CM_SCACHETYPE_MOUNTPOINT) + { attrs = SMB_ATTR_DIRECTORY; - else +#ifdef SPECIAL_FOLDERS +#ifdef AFS_FREELANCE_CLIENT + if ( cm_freelanceEnabled && + scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && + scp->fid.volume==AFS_FAKE_ROOT_VOL_ID && + scp->fid.vnode==0x1 && scp->fid.unique==0x1) { + attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */ + } +#endif /* AFS_FREELANCE_CLIENT */ +#endif /* SPECIAL_FOLDERS */ + } else attrs = 0; /* @@ -1300,7 +1311,7 @@ long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp, { int matchType = 0; smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp; - if(!strnicmp(dep->name, vrock->shareName, 12)) { + if (!strnicmp(dep->name, vrock->shareName, 12)) { if(!stricmp(dep->name, vrock->shareName)) matchType = SMB_FINDSHARE_EXACT_MATCH; else @@ -1464,7 +1475,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL); cm_ReleaseSCache(cm_rootSCachep); - if(vrock.matchType) { + if (vrock.matchType) { sprintf(pathName,"/%s/",vrock.match); *pathNamep = strdup(strlwr(pathName)); free(vrock.match); @@ -1546,11 +1557,11 @@ int smb_FindShareCSCPolicy(char *shareName) /* find a dir search structure by cookie value, and return it held. * Must be called with smb_globalLock held. */ -smb_dirSearch_t *smb_FindDirSearchNL(long cookie) +smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie) { smb_dirSearch_t *dsp; - for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) { + for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) { if (dsp->cookie == cookie) { if (dsp != smb_firstDirSearchp) { /* move to head of LRU queue, too, if we're not already there */ @@ -1562,7 +1573,9 @@ smb_dirSearch_t *smb_FindDirSearchNL(long cookie) if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q; } + lock_ObtainMutex(&dsp->mx); dsp->refCount++; + lock_ReleaseMutex(&dsp->mx); break; } } @@ -1572,10 +1585,9 @@ smb_dirSearch_t *smb_FindDirSearchNL(long cookie) void smb_DeleteDirSearch(smb_dirSearch_t *dsp) { lock_ObtainWrite(&smb_globalLock); - dsp->flags |= SMB_DIRSEARCH_DELETE; - lock_ReleaseWrite(&smb_globalLock); lock_ObtainMutex(&dsp->mx); - if(dsp->scp != NULL) { + dsp->flags |= SMB_DIRSEARCH_DELETE; + if (dsp->scp != NULL) { lock_ObtainMutex(&dsp->scp->mx); if (dsp->flags & SMB_DIRSEARCH_BULKST) { dsp->flags &= ~SMB_DIRSEARCH_BULKST; @@ -1585,37 +1597,47 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp) lock_ReleaseMutex(&dsp->scp->mx); } lock_ReleaseMutex(&dsp->mx); + lock_ReleaseWrite(&smb_globalLock); } -void smb_ReleaseDirSearch(smb_dirSearch_t *dsp) +/* Must be called with the smb_globalLock held */ +void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp) { cm_scache_t *scp; scp = NULL; - lock_ObtainWrite(&smb_globalLock); + lock_ObtainMutex(&dsp->mx); osi_assert(dsp->refCount-- > 0); if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) { if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q); osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q); + lock_ReleaseMutex(&dsp->mx); lock_FinalizeMutex(&dsp->mx); scp = dsp->scp; free(dsp); + } else { + lock_ReleaseMutex(&dsp->mx); } - lock_ReleaseWrite(&smb_globalLock); - /* do this now to avoid spurious locking hierarchy creation */ if (scp) cm_ReleaseSCache(scp); } +void smb_ReleaseDirSearch(smb_dirSearch_t *dsp) +{ + lock_ObtainWrite(&smb_globalLock); + smb_ReleaseDirSearchNoLock(dsp); + lock_ReleaseWrite(&smb_globalLock); +} + /* find a dir search structure by cookie value, and return it held */ smb_dirSearch_t *smb_FindDirSearch(long cookie) { smb_dirSearch_t *dsp; lock_ObtainWrite(&smb_globalLock); - dsp = smb_FindDirSearchNL(cookie); + dsp = smb_FindDirSearchNoLock(cookie); lock_ReleaseWrite(&smb_globalLock); return dsp; } @@ -1650,15 +1672,14 @@ void smb_GCDirSearches(int isV3) } /* don't do more than this */ - if (victimCount >= SMB_DIRSEARCH_GCMAX) break; + if (victimCount >= SMB_DIRSEARCH_GCMAX) + break; } /* now release them */ - lock_ReleaseWrite(&smb_globalLock); - for(i = 0; i < victimCount; i++) { - smb_ReleaseDirSearch(victimsp[i]); + for (i = 0; i < victimCount; i++) { + smb_ReleaseDirSearchNoLock(victimsp[i]); } - lock_ObtainWrite(&smb_globalLock); } /* function for allocating a dir search entry. We need these to remember enough context @@ -1677,25 +1698,27 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3) counter = 0; /* what's the biggest ID allowed in this version of the protocol */ - if (isV3) maxAllowed = 65535; - else maxAllowed = 255; + maxAllowed = isV3 ? 65535 : 255; - while(1) { + while (1) { /* twice so we have enough tries to find guys we GC after one pass; * 10 extra is just in case I mis-counted. */ - if (++counter > 2*maxAllowed+10) osi_panic("afsd: dir search cookie leak", - __FILE__, __LINE__); + if (++counter > 2*maxAllowed+10) + osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__); + if (smb_dirSearchCounter > maxAllowed) { smb_dirSearchCounter = 1; - smb_GCDirSearches(isV3); /* GC some (drops global lock) */ + smb_GCDirSearches(isV3); /* GC some */ } - dsp = smb_FindDirSearchNL(smb_dirSearchCounter); + dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter); if (dsp) { /* don't need to watch for refcount zero and deleted, since * we haven't dropped the global lock. */ + lock_ObtainMutex(&dsp->mx); dsp->refCount--; + lock_ReleaseMutex(&dsp->mx); ++smb_dirSearchCounter; continue; } @@ -1703,7 +1726,8 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3) dsp = malloc(sizeof(*dsp)); memset(dsp, 0, sizeof(*dsp)); osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q); - if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q; + if (!smb_lastDirSearchp) + smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q; dsp->cookie = smb_dirSearchCounter; ++smb_dirSearchCounter; dsp->refCount = 1; @@ -2275,6 +2299,13 @@ void smb_MapNTError(long code, unsigned long *NTStatusp) else if (code == CM_ERROR_GSSCONTINUE) { NTStatus = 0xC0000016L; /* more processing required */ } + else if (code == CM_ERROR_TOO_MANY_SYMLINKS) { +#ifdef COMMENT + NTStatus = 0xC0000280L; /* reparse point not resolved */ +#else + NTStatus = 0xC0000022L; /* Access Denied */ +#endif + } else { NTStatus = 0xC0982001L; /* SMB non-specific error */ } @@ -3402,7 +3433,6 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou else { spacep = inp->spacep; smb_StripLastComponent(spacep->data, NULL, pathp); - lock_ReleaseMutex(&dsp->mx); code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); if (code) { lock_ReleaseMutex(&dsp->mx); @@ -3413,9 +3443,9 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp); - lock_ObtainMutex(&dsp->mx); if (code == 0) { - if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp); + if (dsp->scp != 0) + cm_ReleaseSCache(dsp->scp); dsp->scp = scp; /* we need one hold for the entry we just stored into, * and one for our own processing. When we're done with this @@ -3520,13 +3550,14 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou lock_ObtainRead(&scp->bufCreateLock); code = buf_Get(scp, &thyper, &bufferp); lock_ReleaseRead(&scp->bufCreateLock); + lock_ObtainMutex(&dsp->mx); /* now, if we're doing a star match, do bulk fetching of all of * the status info for files in the dir. */ if (starPattern) { - smb_ApplyDirListPatches(&dirListPatchesp, userp, - &req); + smb_ApplyDirListPatches(&dirListPatchesp, userp, &req); + lock_ObtainMutex(&scp->mx); if ((dsp->flags & SMB_DIRSEARCH_BULKST) && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) { @@ -3539,11 +3570,13 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou } else cm_TryBulkStat(scp, &thyper, userp, &req); } + } else { + lock_ObtainMutex(&scp->mx); } - - lock_ObtainMutex(&scp->mx); + lock_ReleaseMutex(&dsp->mx); if (code) break; + bufferOffset = thyper; /* now get the data in the cache */ @@ -4917,8 +4950,7 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp, rock.name = pathp; rock.vnode = scp; - code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, - userp, reqp, NULL); + code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL); if (code == CM_ERROR_STOPNOW) *newPathp = rock.fullName; else @@ -6932,6 +6964,7 @@ DWORD smb_ServerExceptionFilter(void) { } afsd_ForceTrace(TRUE); + buf_ForceTrace(TRUE); return EXCEPTION_CONTINUE_SEARCH; } #endif diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 9c8691f64..980da2c5a 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -72,9 +72,20 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp) unsigned long attrs; if (scp->fileType == CM_SCACHETYPE_DIRECTORY || - scp->fileType == CM_SCACHETYPE_MOUNTPOINT) + scp->fileType == CM_SCACHETYPE_MOUNTPOINT) + { attrs = SMB_ATTR_DIRECTORY; - else +#ifdef SPECIAL_FOLDERS +#ifdef AFS_FREELANCE_CLIENT + if ( cm_freelanceEnabled && + scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && + scp->fid.volume==AFS_FAKE_ROOT_VOL_ID && + scp->fid.vnode==0x1 && scp->fid.unique==0x1) { + attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */ + } +#endif /* AFS_FREELANCE_CLIENT */ +#endif /* SPECIAL_FOLDERS */ + } else attrs = 0; /* * We used to mark a file RO if it was in an RO volume, but that @@ -2477,8 +2488,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp, rock.shortName = shortName; rock.vnode = vnode; rock.maskp = lastNamep; - code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp, - reqp, NULL); + code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp, reqp, NULL); cm_ReleaseSCache(dscp); @@ -3575,8 +3585,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t pathp = ((char *) p->parmsp) + 12; /* points to path */ nextCookie = 0; maskp = strrchr(pathp, '\\'); - if (maskp == NULL) maskp = pathp; - else maskp++; /* skip over backslash */ + if (maskp == NULL) + maskp = pathp; + else + maskp++; /* skip over backslash */ strcpy(dsp->mask, maskp); /* and save mask */ /* track if this is likely to match a lot of entries */ starPattern = smb_V3IsStarMask(maskp); @@ -3585,7 +3597,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t osi_assert(p->opcode == 2); /* find next; obtain basic parameters from request or open dir file */ dsp = smb_FindDirSearch(p->parmsp[0]); - if (!dsp) return CM_ERROR_BADFD; + if (!dsp) + return CM_ERROR_BADFD; attribute = dsp->attribute; maxCount = p->parmsp[1]; infoLevel = p->parmsp[2]; @@ -3653,10 +3666,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t else { spacep = cm_GetSpace(); smb_StripLastComponent(spacep->data, NULL, pathp); - lock_ReleaseMutex(&dsp->mx); - code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); if (code) { + lock_ReleaseMutex(&dsp->mx); cm_ReleaseUser(userp); smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES); smb_FreeTran2Packet(outp); @@ -3669,9 +3681,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t userp, tidPathp, &req, &scp); cm_FreeSpace(spacep); - lock_ObtainMutex(&dsp->mx); if (code == 0) { - if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp); + if (dsp->scp != 0) + cm_ReleaseSCache(dsp->scp); dsp->scp = scp; /* we need one hold for the entry we just stored into, * and one for our own processing. When we're done @@ -3784,6 +3796,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t lock_ObtainRead(&scp->bufCreateLock); code = buf_Get(scp, &thyper, &bufferp); lock_ReleaseRead(&scp->bufCreateLock); + lock_ObtainMutex(&dsp->mx); /* now, if we're doing a star match, do bulk fetching * of all of the status info for files in the dir. @@ -3792,6 +3805,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req); + lock_ObtainMutex(&scp->mx); if ((dsp->flags & SMB_DIRSEARCH_BULKST) && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) { /* Don't bulk stat if risking timeout */ @@ -3803,10 +3817,13 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t } else cm_TryBulkStat(scp, &thyper, userp, &req); } + } else { + lock_ObtainMutex(&scp->mx); } + lock_ReleaseMutex(&dsp->mx); + if (code) + break; - lock_ObtainMutex(&scp->mx); - if (code) break; bufferOffset = thyper; /* now get the data in the cache */ diff --git a/src/WINNT/afsd/symlink.c b/src/WINNT/afsd/symlink.c index 69fe625fd..0b7322ae1 100644 --- a/src/WINNT/afsd/symlink.c +++ b/src/WINNT/afsd/symlink.c @@ -22,8 +22,6 @@ #include #include -typedef long afs_int32; - #include "fs_utils.h" #include "cmd.h" @@ -243,6 +241,11 @@ register struct cmd_syndesc *as; { /* create symlink with a special pioctl for Windows NT, since it doesn't * have a symlink system call. */ + + /* TODO: Code needs to go here to prevent the creation of symlinks + * in \\AFS\all when not in the "AFS Client Admins" group. + */ + blob.out_size = 0; blob.in_size = 1 + strlen(space); blob.in = space; diff --git a/src/WINNT/afssvrcfg/NTMakefile b/src/WINNT/afssvrcfg/NTMakefile index 257130f24..d74932b89 100644 --- a/src/WINNT/afssvrcfg/NTMakefile +++ b/src/WINNT/afssvrcfg/NTMakefile @@ -90,6 +90,9 @@ lang:: # Local clean target; augments predefined clean target clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. mkdir: -mkdir $(OUT)\lang diff --git a/src/WINNT/afssvrcpa/NTMakefile b/src/WINNT/afssvrcpa/NTMakefile index 487e7b215..c9dfd8205 100644 --- a/src/WINNT/afssvrcpa/NTMakefile +++ b/src/WINNT/afssvrcpa/NTMakefile @@ -55,7 +55,9 @@ lang:: # Local clean target; augments predefined clean target clean:: - + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. mkdir: -mkdir $(OUT)\lang diff --git a/src/WINNT/afssvrmgr/NTMakefile b/src/WINNT/afssvrmgr/NTMakefile index 97619e3e5..0526ac91a 100644 --- a/src/WINNT/afssvrmgr/NTMakefile +++ b/src/WINNT/afssvrmgr/NTMakefile @@ -116,9 +116,14 @@ install : $(EXEFILE) lang $(OUT)\svrmgr_stub.res : AFS_component_version_number.h +clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. + mkdir: -mkdir $(OUT)\lang cd lang nmake /nologo /f ntmakefile SRC=$(SRC) OBJ=$(OBJ) mkdir cd .. - + diff --git a/src/WINNT/afsusrmgr/NTMakefile b/src/WINNT/afsusrmgr/NTMakefile index 422c47816..3514cc0d5 100644 --- a/src/WINNT/afsusrmgr/NTMakefile +++ b/src/WINNT/afsusrmgr/NTMakefile @@ -93,6 +93,11 @@ install : $(EXEFILE) lang $(OUT)\AfsUsrMgr_stub.res : AFS_component_version_number.h +clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. + mkdir: -mkdir $(OUT)\lang cd lang diff --git a/src/WINNT/client_config/config.cpp b/src/WINNT/client_config/config.cpp index d39f24fc3..f3ea6628f 100644 --- a/src/WINNT/client_config/config.cpp +++ b/src/WINNT/client_config/config.cpp @@ -671,51 +671,67 @@ BOOL Config_SetNumDaemons (ULONG cDaemons, ULONG *pStatus) void Config_GetSysName (LPTSTR pszName) { - if (!Config_ReadGlobalString (TEXT("SysName"), pszName, MAX_PATH)) - lstrcpy (pszName, TEXT("i386_nt40")); + if (!Config_ReadGlobalString (TEXT("SysName"), pszName, MAX_PATH)) + lstrcpy (pszName, TEXT("i386_nt40")); } BOOL Config_SetSysName (LPCTSTR pszName, ULONG *pStatus) { - BOOL rc = TRUE; - ULONG status = 0; - - if (Config_GetServiceState() == SERVICE_RUNNING) - { - struct { - ULONG cbData; - TCHAR szData[ PIOCTL_MAXSIZE ]; - } InData; - memset (&InData, 0x00, sizeof(InData)); - InData.cbData = lstrlen(pszName); - lstrcpy (InData.szData, pszName); - - BYTE OutData[ PIOCTL_MAXSIZE ]; - memset (OutData, 0x00, sizeof(OutData)); - - struct ViceIoctl IOInfo; - IOInfo.in_size = sizeof(ULONG) +lstrlen(pszName) +1; - IOInfo.in = (char *)&InData; - IOInfo.out = (char *)OutData; - IOInfo.out_size = PIOCTL_MAXSIZE; - - if ((status = pioctl (0, VIOC_AFS_SYSNAME, &IOInfo, 1)) != 0) - { - rc = FALSE; - } - } - - if (rc) - { - Config_WriteGlobalString (TEXT("SysName"), pszName); - } - - if (pStatus && !rc) - *pStatus = status; - if (!rc) - Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("%ld"), status); - return rc; + BOOL rc = TRUE; + ULONG status = 0; + + if (Config_GetServiceState() == SERVICE_RUNNING) + { + struct { + ULONG cbData; + TCHAR szData[ PIOCTL_MAXSIZE ]; + } InData; + memset (&InData, 0x00, sizeof(InData)); + USHORT i=0, j=0, len=lstrlen(pszName); + + if ( len == 0 ) { + Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("A sysname must be specified")); + return(-1); + } + + while ( pszName[i] ) { + if ( !isspace(pszName[i]) ) { + InData.szData[j++] = pszName[i]; + } else if (InData.szData[j-1] != '\0') { + InData.szData[j++] = '\0'; + InData.cbData++; + } + i++; + } + InData.szData[j++] = '\0'; + InData.cbData++; /* one word */ + + BYTE OutData[ PIOCTL_MAXSIZE ]; + memset (OutData, 0x00, sizeof(OutData)); + + struct ViceIoctl IOInfo; + IOInfo.in_size = sizeof(ULONG) + j; + IOInfo.in = (char *)&InData; + IOInfo.out = (char *)OutData; + IOInfo.out_size = PIOCTL_MAXSIZE; + + if ((status = pioctl (0, VIOC_AFS_SYSNAME, &IOInfo, 1)) != 0) + { + rc = FALSE; + } + } + + if (rc) + { + Config_WriteGlobalString (TEXT("SysName"), pszName); + } + + if (pStatus && !rc) + *pStatus = status; + if (!rc) + Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("%ld"), status); + return rc; } diff --git a/src/WINNT/client_creds/NTMakefile b/src/WINNT/client_creds/NTMakefile index f577152aa..b58c51e07 100644 --- a/src/WINNT/client_creds/NTMakefile +++ b/src/WINNT/client_creds/NTMakefile @@ -127,6 +127,11 @@ lang :: $(OUT)\afscreds_stub.res : afscreds_stub.rc AFS_component_version_number.h +clean:: + $(CD) lang + for /f %l in ('dir /B ??_??') do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean + $(CD) .. + mkdir: -mkdir $(OUT)\lang cd lang diff --git a/src/WINNT/client_exp/lang/en_US/afs_shl_ext.rc b/src/WINNT/client_exp/lang/en_US/afs_shl_ext.rc index 0933ba43a..75edee5af 100644 --- a/src/WINNT/client_exp/lang/en_US/afs_shl_ext.rc +++ b/src/WINNT/client_exp/lang/en_US/afs_shl_ext.rc @@ -429,7 +429,21 @@ BEGIN PUSHBUTTON "OK",IDOK,22,53,45,14 PUSHBUTTON "Cancel",IDCANCEL,92,53,45,14 PUSHBUTTON "Help",9,167,53,45,14 - LTEXT "Share Name:",IDC_STATIC,18,10,29,8 + LTEXT "Submount Name:",IDC_STATIC,18,10,29,8 + LTEXT "Path Name:",IDC_STATIC,19,25,28,8 +END + +IDD_SYMBOLICLINK_ADD DIALOG DISCARDABLE 0, 0, 235, 79 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add Symbolic Link" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_NAME,62,8,163,12,ES_AUTOHSCROLL + EDITTEXT IDC_DIR,62,23,163,12,ES_AUTOHSCROLL + PUSHBUTTON "OK",IDOK,22,53,45,14 + PUSHBUTTON "Cancel",IDCANCEL,92,53,45,14 + PUSHBUTTON "Help",9,167,53,45,14 + LTEXT "Link Name:",IDC_STATIC,18,10,29,8 LTEXT "Path Name:",IDC_STATIC,19,25,28,8 END diff --git a/src/WINNT/client_exp/make_symbolic_link_dlg.cpp b/src/WINNT/client_exp/make_symbolic_link_dlg.cpp index d1889fbc1..ff3a29de5 100644 --- a/src/WINNT/client_exp/make_symbolic_link_dlg.cpp +++ b/src/WINNT/client_exp/make_symbolic_link_dlg.cpp @@ -51,7 +51,7 @@ void CMakeSymbolicLinkDlg::DoDataExchange(CDataExchange* pDX) DDX_Text(pDX, IDC_NAME, m_strName); DDV_MaxChars(pDX, m_strName, 63); DDX_Text(pDX, IDC_DIR, m_strDir); - DDV_MaxChars(pDX, m_strDir, 63); + DDV_MaxChars(pDX, m_strDir, 255); //}}AFX_DATA_MAP } diff --git a/src/WINNT/install/wix/NTMakefile b/src/WINNT/install/wix/NTMakefile index 8ea9570bf..b335a430c 100644 --- a/src/WINNT/install/wix/NTMakefile +++ b/src/WINNT/install/wix/NTMakefile @@ -62,9 +62,8 @@ $(WIXOBJ): openafs.wxs $(WIXINCLUDES) # Cleanup clean:: - for %l in ( $(LANGUAGES) ) do ( + for %l in ( $(LANGUAGES) ) do \ $(MAKE) /f NTMakefile /nologo LANG=%l lang_clean - ) $(CD) custom $(MAKE) /f NTMakefile /nologo clean $(CD) .. diff --git a/src/WINNT/install/wix/config.wxi b/src/WINNT/install/wix/config.wxi index e4702b09d..bd7af64ed 100644 --- a/src/WINNT/install/wix/config.wxi +++ b/src/WINNT/install/wix/config.wxi @@ -103,6 +103,19 @@ + + + + + + + + + + + + + @@ -150,4 +163,6 @@ + + diff --git a/src/WINNT/install/wix/feature.wxi b/src/WINNT/install/wix/feature.wxi index 273b9042c..d786b2d75 100644 --- a/src/WINNT/install/wix/feature.wxi +++ b/src/WINNT/install/wix/feature.wxi @@ -1,42 +1,29 @@  - - - - - - - - - - - - - + InstallDefault="followParent" Level="30" Title="$(loc.StrAFSClientDesc)"> - + - + VersionNT = 500 And ServicePackLevel < 3 - + CREDSSTARTUP = 0 + InstallDefault="$(var.DebugSymInstallDefault)" Level="$(var.DebugSymLowLevel)" Title="$(loc.StrAFSClientDebugDesc)"> @@ -98,7 +85,7 @@ + InstallDefault="followParent" Level="130" Title="$(loc.StrAFSServerDesc)"> @@ -147,7 +134,7 @@ + InstallDefault="$(var.DebugSymInstallDefault)" Level="$(var.DebugSymHighLevel)" Title="$(loc.StrAFSServerDebugDesc)"> @@ -159,7 +146,7 @@ + Display="expand" InstallDefault="followParent" Level="130" Title="$(loc.StrAFSCCDesc)"> @@ -197,7 +184,7 @@ + Display="expand" InstallDefault="$(var.DebugSymInstallDefault)" Level="$(var.DebugSymHighLevel)" Title="$(loc.StrAFSCCDebugDesc)"> @@ -212,7 +199,7 @@ + InstallDefault="followParent" Level="130" Title="$(loc.StrAFSSDKDesc)"> @@ -227,7 +214,7 @@ + InstallDefault="$(var.DebugSymInstallDefault)" Level="$(var.DebugSymHighLevel)" Title="$(loc.StrAFSSDKDebugDesc)"> @@ -236,7 +223,7 @@ + Display="expand" InstallDefault="followParent" Level="130" Title="$(loc.StrAFSDocDesc)"> diff --git a/src/WINNT/install/wix/files.wxi b/src/WINNT/install/wix/files.wxi index 0a61cca5d..b2bf6a7c1 100644 --- a/src/WINNT/install/wix/files.wxi +++ b/src/WINNT/install/wix/files.wxi @@ -1,6 +1,6 @@ - + @@ -19,7 +19,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -362,8 +362,8 @@ - - + + @@ -380,7 +380,7 @@ - + @@ -668,7 +668,7 @@ - + @@ -715,7 +715,7 @@ - + @@ -730,7 +730,7 @@ - + OLDCELLSERVDB = "" @@ -740,7 +740,7 @@ OLDCELLSERVDB <> "" - + @@ -860,12 +860,12 @@ - + - + @@ -898,7 +898,7 @@ - + @@ -1034,7 +1034,7 @@ - + @@ -1063,7 +1063,7 @@ - + @@ -1115,7 +1115,7 @@ - + @@ -1134,7 +1134,7 @@ - + @@ -1178,10 +1178,10 @@ - - - - + + + + @@ -1284,7 +1284,7 @@ - + diff --git a/src/WINNT/install/wix/openafs.wxs b/src/WINNT/install/wix/openafs.wxs index 2ca393c78..d0c493b29 100644 --- a/src/WINNT/install/wix/openafs.wxs +++ b/src/WINNT/install/wix/openafs.wxs @@ -153,7 +153,7 @@ BinaryKey="BIN_afsCustom" DllEntry="UninstallNsisInstallation" Execute="immediate" /> - event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE, - FALSE, (LPCTSTR) eventName); + new->event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE, + FALSE, (LPCTSTR) 0); if (new->event == NULL) { free(new); new = NULL; diff --git a/src/sys/pioctl_nt.c b/src/sys/pioctl_nt.c index 2441a450f..cd2ca487f 100644 --- a/src/sys/pioctl_nt.c +++ b/src/sys/pioctl_nt.c @@ -530,7 +530,7 @@ pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow) CloseHandle(reqHandle); errno = CMtoUNIXerror(temp); if ( IoctlDebug() ) - fprintf(stderr, "pioctl temp != 0: %d\r\n",temp); + fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp); return -1; } -- 2.39.5