diff --git a/config/alfresco/desktop/Alfresco.exe b/config/alfresco/desktop/Alfresco.exe index 85a1b543eb..1e4a82606d 100644 Binary files a/config/alfresco/desktop/Alfresco.exe and b/config/alfresco/desktop/Alfresco.exe differ diff --git a/source/cpp/CAlfrescoApp/CAlfrescoApp.cpp b/source/cpp/CAlfrescoApp/CAlfrescoApp.cpp index 18221d552a..0e4f2a72d6 100644 --- a/source/cpp/CAlfrescoApp/CAlfrescoApp.cpp +++ b/source/cpp/CAlfrescoApp/CAlfrescoApp.cpp @@ -321,7 +321,7 @@ bool CAlfrescoApp::buildDesktopParameters( AlfrescoInterface& alfresco, StringLi // Convert the path to a UNC path String uncPath = alfresco.getRootPath(); - uncPath.append( curFile.substring(2)); + uncPath.append( curFile.substring(3)); curFile = uncPath; } @@ -356,7 +356,8 @@ bool CAlfrescoApp::buildDesktopParameters( AlfrescoInterface& alfresco, StringLi // If the path is to a file that is not on the Alfresco share the file will need to be copied, // after checking the status of a matching file in the Alfresco folder - if ( curFile.length() >= 3 && curFile.substring(1,3).equals( L":\\")) { + if ( curFile.length() >= 3 && curFile.startsWithIgnoreCase( alfresco.getDrivePath()) == false && + curFile.substring(1,3).equals( L":\\")) { // Check if the action supports local files diff --git a/source/cpp/CAlfrescoApp/includes/alfresco/Alfresco.hpp b/source/cpp/CAlfrescoApp/includes/alfresco/Alfresco.hpp index 273cca3825..57a1ded5ee 100644 --- a/source/cpp/CAlfrescoApp/includes/alfresco/Alfresco.hpp +++ b/source/cpp/CAlfrescoApp/includes/alfresco/Alfresco.hpp @@ -53,8 +53,8 @@ namespace Alfresco { #define FSCTL_ALFRESCO_FILESTS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) // Version 1 FSCTL_ALFRESCO_CHECKOUT - 0x802 // Version 1 FSCTL_ALFRESCO_CHECKIN - 0x803 - #define FSCTL_ALFRESCO_GETACTIONINFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x804, METHOD_BUFFERED, FILE_WRITE_DATA) - #define FSCTL_ALFRESCO_RUNACTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x805, METHOD_BUFFERED, FILE_WRITE_DATA) + #define FSCTL_ALFRESCO_GETACTIONINFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) + #define FSCTL_ALFRESCO_RUNACTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_ALFRESCO_GETAUTHTICKET CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) // Request signature bytes diff --git a/source/cpp/CAlfrescoApp/source/alfresco/Alfresco.cpp b/source/cpp/CAlfrescoApp/source/alfresco/Alfresco.cpp index b221122c2f..c81d0dabc7 100644 --- a/source/cpp/CAlfrescoApp/source/alfresco/Alfresco.cpp +++ b/source/cpp/CAlfrescoApp/source/alfresco/Alfresco.cpp @@ -330,12 +330,16 @@ bool AlfrescoInterface::setRootPath( const wchar_t* rootPath) { if ( m_handle != INVALID_HANDLE_VALUE) CloseHandle(m_handle); + // Clear the root path + + m_rootPath = ""; + // Check if the path is to a mapped drive String path = rootPath; String alfPath = rootPath; - if ( alfPath.length() >= 3 && alfPath.substring(1,3).equals( L":\\")) { + if ( alfPath.length() >= 2 && alfPath.charAt(1) == ':') { // Try and convert the local path to a UNC path @@ -353,6 +357,10 @@ bool AlfrescoInterface::setRootPath( const wchar_t* rootPath) { if ( alfPath.endsWith( PathSeperator) == false) alfPath.append( PathSeperator); + m_rootPath = alfPath; + + // Build the full UNC path to the target + if ( path.length() > 3) alfPath.append( path.substring( 3)); } @@ -395,13 +403,15 @@ bool AlfrescoInterface::setRootPath( const wchar_t* rootPath) { // Set the root path - int pos = m_uncPath.indexOf( PathSeperator, 2); - if ( pos != -1) { - pos = m_uncPath.indexOf( PathSeperator, pos + 1); - if ( pos == -1) - m_rootPath = m_uncPath; - else - m_rootPath = m_uncPath.substring(0, pos); + if ( m_rootPath.length() == 0) { + int pos = m_uncPath.indexOf( PathSeperator, 2); + if ( pos != -1) { + pos = m_uncPath.indexOf( PathSeperator, pos + 1); + if ( pos == -1) + m_rootPath = m_uncPath; + else + m_rootPath = m_uncPath.substring(0, pos); + } } } diff --git a/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java b/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java index b8a80959c3..8ecfa044a2 100644 --- a/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java +++ b/source/java/org/alfresco/filesys/AbstractServerConfigurationBean.java @@ -34,8 +34,6 @@ import java.util.Enumeration; import java.util.Locale; import java.util.StringTokenizer; -import net.sf.acegisecurity.AuthenticationManager; - import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.filesys.alfresco.AlfrescoClientInfoFactory; import org.alfresco.filesys.alfresco.ExtendedDiskInterface; @@ -430,6 +428,23 @@ public abstract class AbstractServerConfigurationBean extends ServerConfiguratio ClientInfo.setFactory( new AlfrescoClientInfoFactory()); + // We need to check for a WINS server configuration in the CIFS server config section to initialize + // the NetBIOS name lookups to use WINS rather broadcast lookups, which may be used to get the local + // domain + + try { + + // Get the CIFS server config section and extract the WINS server config, if available + + processWINSServerConfig(); + } + catch (Exception ex) { + + // Configuration error + + logger.error("File server configuration error (WINS), " + ex.getMessage(), ex); + } + // Initialize the filesystems try @@ -531,6 +546,8 @@ public abstract class AbstractServerConfigurationBean extends ServerConfiguratio protected abstract void processNFSServerConfig(); protected abstract void processFTPServerConfig(); + + protected void processWINSServerConfig() {} /** * Close the configuration bean diff --git a/source/java/org/alfresco/filesys/ServerConfigurationBean.java b/source/java/org/alfresco/filesys/ServerConfigurationBean.java index 07cd4f7b17..faa14f2e6f 100644 --- a/source/java/org/alfresco/filesys/ServerConfigurationBean.java +++ b/source/java/org/alfresco/filesys/ServerConfigurationBean.java @@ -1880,6 +1880,20 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean { boolean changeNotify = elem.getChild("disableChangeNotification") == null ? true : false; + // Check if filesyststem debug flags are enabled + + ConfigElement filesysDbgElem = elem.getChild("debug"); + if (filesysDbgElem != null) + { + // Check for filesystem debug flags + + String flags = filesysDbgElem.getAttribute("flags"); + + // Set the filesystem debug flags + + filesysContext.setDebug( flags); + } + // Create the shared filesystem filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext); @@ -2624,4 +2638,51 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean { return desktopActions; } + /** + * Parse the CIFS server config section to get the WINS server details, if available + * + * @param config Config + */ + protected void processWINSServerConfig( Config config) + { + // Check if WINS servers are configured + + ConfigElement elem = config.getConfigElement("WINS"); + + if (elem != null) + { + + // Get the primary WINS server + + ConfigElement priWinsElem = elem.getChild("primary"); + + if (priWinsElem == null || priWinsElem.getValue().length() == 0) + throw new AlfrescoRuntimeException("No primary WINS server configured"); + + // Validate the WINS server address + + InetAddress primaryWINS = null; + + try + { + primaryWINS = InetAddress.getByName(priWinsElem.getValue()); + } + catch (UnknownHostException ex) + { + throw new AlfrescoRuntimeException("Invalid primary WINS server address, " + priWinsElem.getValue()); + } + + // Pass the setting to the NetBIOS session class + + NetBIOSSession.setDefaultWINSServer(primaryWINS); + } + } + + /** + * Parse the CIFS server config section to get the WINS server details, if available + */ + protected void processWINSServerConfig() + { + processWINSServerConfig(m_configService.getConfig(ConfigCIFS, configCtx)); + } } diff --git a/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java b/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java index 4b0efcaa15..45e5568e48 100644 --- a/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java +++ b/source/java/org/alfresco/filesys/alfresco/AlfrescoContext.java @@ -27,6 +27,7 @@ package org.alfresco.filesys.alfresco; import java.net.InetAddress; import java.util.Enumeration; import java.util.List; +import java.util.StringTokenizer; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.filesys.config.GlobalDesktopActionConfigBean; @@ -52,6 +53,20 @@ public abstract class AlfrescoContext extends DiskDeviceContext private static final String TokenLocalName = "${localname}"; + // Debug levels + + public final static int DBG_FILE = 0x00000001; // file/folder create/delete + public final static int DBG_FILEIO = 0x00000002; // file read/write/truncate + public final static int DBG_SEARCH = 0x00000004; // folder search + public final static int DBG_INFO = 0x00000008; // file/folder information + public final static int DBG_LOCK = 0x00000010; // file byte range locking + public final static int DBG_PSEUDO = 0x00000020; // pseudo files/folders + public final static int DBG_RENAME = 0x00000040; // rename file/folder + + // Filesystem debug flag strings + + private static final String m_filesysDebugStr[] = { "FILE", "FILEIO", "SEARCH", "INFO", "LOCK", "PSEUDO", "RENAME" }; + // File state table and associated file state reaper private FileStateTable m_stateTable; @@ -76,6 +91,12 @@ public abstract class AlfrescoContext extends DiskDeviceContext private IOControlHandler m_ioHandler; + // Debug flags + // + // Requires the logger to be enabled for debug output + + public int m_debug; + public AlfrescoContext() { // Default the filesystem to look like an 80Gb sized disk with 90% free space @@ -456,6 +477,65 @@ public abstract class AlfrescoContext extends DiskDeviceContext m_ioHandler = ioctlHandler; } + /** + * Set the debug flags, also requires the logger to be enabled for debug output + * + * @param dbg int + */ + public final void setDebug(String flagsStr) + { + int filesysDbg = 0; + + if (flagsStr != null) + { + // Parse the flags + + StringTokenizer token = new StringTokenizer(flagsStr.toUpperCase(), ","); + + while (token.hasMoreTokens()) + { + // Get the current debug flag token + + String dbg = token.nextToken().trim(); + + // Find the debug flag name + + int idx = 0; + boolean match = false; + + while (idx < m_filesysDebugStr.length && match == false) + { + if ( m_filesysDebugStr[idx].equalsIgnoreCase(dbg) == true) + match = true; + else + idx++; + } + + if (match == false) + throw new AlfrescoRuntimeException("Invalid filesystem debug flag, " + dbg); + + // Set the debug flag + + filesysDbg += 1 << idx; + } + + // Set the debug flags + + m_debug = filesysDbg; + } + } + + /** + * Check if a debug flag is enabled + * + * @param flg int + * @return boolean + */ + public final boolean hasDebug(int flg) + { + return (m_debug & flg) != 0 ? true : false; + } + /** * Close the filesystem context */ diff --git a/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java b/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java index f53df4d83a..a6a4e60f72 100644 --- a/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java +++ b/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java @@ -413,7 +413,7 @@ public abstract class CifsAuthenticatorBase extends CifsAuthenticator implements // Check the account type and setup the authentication context - if (client.isNullSession()) + if (client == null || client.isNullSession()) { // Clear the authentication, null user should not be allowed to do any service calls diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java index 71c6f6bb60..6d5338ed83 100644 --- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java +++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver.java @@ -34,6 +34,7 @@ import javax.transaction.UserTransaction; import org.alfresco.config.ConfigElement; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.filesys.alfresco.AlfrescoContext; import org.alfresco.filesys.alfresco.AlfrescoDiskDriver; import org.alfresco.filesys.alfresco.AlfrescoNetworkFile; import org.alfresco.filesys.state.FileState; @@ -64,6 +65,7 @@ import org.alfresco.jlan.server.filesys.pseudo.PseudoNetworkFile; import org.alfresco.jlan.server.locking.FileLockingInterface; import org.alfresco.jlan.server.locking.LockManager; import org.alfresco.jlan.smb.SharingMode; +import org.alfresco.jlan.smb.WinNT; import org.alfresco.jlan.smb.server.SMBServer; import org.alfresco.jlan.smb.server.SMBSrvSession; import org.alfresco.jlan.util.WildCard; @@ -701,7 +703,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug( "Added file state for pseudo files folder (getinfo) - " + paths[0]); } else if ( fstate.hasPseudoFiles() == false) @@ -721,7 +723,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug( "Added pseudo files for folder (exists) - " + paths[0]); } @@ -732,7 +734,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa if ( pfile != null) { // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("getInfo using pseudo file info for " + path); FileInfo pseudoFileInfo = pfile.getFileInfo(); @@ -761,7 +763,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("getInfo using cached noderef for path " + path); } @@ -785,7 +787,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("getInfo using cached noderef for parent " + path); } } @@ -796,12 +798,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if (logger.isDebugEnabled()) - { - logger.debug("Getting file information: \n" + - " path: " + path + "\n" + - " file info: " + finfo); - } + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) + logger.debug("Getting file information: path=" + path + " file info: " + finfo); } // Set the file id for the file using the relative path @@ -833,16 +831,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if (logger.isDebugEnabled()) - logger.debug("Getting file information - File not found: \n" + - " path: " + path); + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) + logger.debug("Get file info - file not found, " + path); throw e; } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Get file info - access denied, " + path); // Convert to a filesystem access denied status @@ -853,7 +850,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Get file info error", ex); // Convert to a general I/O exception @@ -875,12 +872,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa */ public SearchContext startSearch(SrvSession sess, TreeConnection tree, String searchPath, int attributes) throws FileNotFoundException { + // Access the device context + + ContentContext ctx = (ContentContext) tree.getContext(); + try { - // Access the device context - - ContentContext ctx = (ContentContext) tree.getContext(); - String searchFileSpec = searchPath; NodeRef searchRootNodeRef = ctx.getRootNode(); FileState searchFolderState = null; @@ -937,7 +934,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) logger.debug("Search using cached noderef for path " + searchPath); } } @@ -948,10 +945,25 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa if ( searchFileSpec.equals( "*.*")) searchFileSpec = "*"; + // Debug + + long startTime = 0L; + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) + startTime = System.currentTimeMillis(); + // Perform the search List results = cifsHelper.getNodeRefs(searchRootNodeRef, searchFileSpec); + // Debug + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) { + long endTime = System.currentTimeMillis(); + if (( endTime - startTime) > 500) + logger.debug("Search for searchPath=" + searchPath + ", searchSpec=" + searchFileSpec + ", searchRootNode=" + searchRootNodeRef + " took " + + ( endTime - startTime) + "ms results=" + results.size()); + } + // Check if there are any pseudo files for the folder being searched, for CIFS only PseudoFileList pseudoList = null; @@ -1021,19 +1033,16 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if (logger.isDebugEnabled()) - { - logger.debug("Started search: \n" + - " search path: " + searchPath + "\n" + - " attributes: " + attributes); - } + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) + logger.debug("Started search: search path=" + searchPath + " attributes=" + attributes); + return searchCtx; } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) logger.debug("Start search - access denied, " + searchPath); // Convert to a file not found status @@ -1044,7 +1053,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_SEARCH)) logger.debug("Start search", ex); // Convert to a file not found status @@ -1064,14 +1073,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa */ public int fileExists(SrvSession sess, TreeConnection tree, String name) { - + ContentContext ctx = (ContentContext) tree.getContext(); int status = FileStatus.Unknown; try { // Check for a cached file state - ContentContext ctx = (ContentContext) tree.getContext(); FileState fstate = null; if ( ctx.hasStateTable()) @@ -1090,7 +1098,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Cache hit - fileExists() " + name + ", sts=" + status); } else @@ -1131,7 +1139,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Added file state for pseudo files folder (exists) - " + paths[0]); } } @@ -1156,7 +1164,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Added pseudo files for folder (exists) - " + paths[0]); } @@ -1173,7 +1181,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Failed to find pseudo file - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Failed to find pseudo file (exists) - " + name); } } @@ -1208,20 +1216,17 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa catch (IOException e) { // Debug - - logger.debug("File exists error, " + name, e); + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) + logger.debug("File exists error, " + name, e); status = FileStatus.NotExist; } // Debug - if (logger.isDebugEnabled()) - { - logger.debug("File status determined: \n" + - " name: " + name + "\n" + - " status: " + status); - } + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) + logger.debug("File status determined: name=" + name + " status=" + FileStatus.asString(status)); // Return the file/folder status @@ -1242,13 +1247,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Create the transaction beginReadTransaction( sess); + ContentContext ctx = (ContentContext) tree.getContext(); try { - // Get the node for the path - - ContentContext ctx = (ContentContext) tree.getContext(); - // Check if pseudo files are enabled if ( hasPseudoFileInterface(ctx)) @@ -1279,7 +1281,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Added file state for pseudo files folder (open) - " + paths[0]); } } @@ -1291,7 +1293,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Added pseudo files for folder (open) - " + paths[0]); } @@ -1308,7 +1310,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Failed to find pseudo file - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_PSEUDO)) logger.debug( "Failed to find pseudo file (open) - " + params.getPath()); } } @@ -1361,46 +1363,102 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa if ( fstate.exists() == false) throw new FileNotFoundException(); - - // Check the file sharing mode - - if ( fstate != null) { - - // Check if the current file open allows the required shared access - - boolean nosharing = false; - - if ( fstate.getOpenCount() > 0) { - - // Check if the file has been opened for exclusive access - - if ( fstate.getSharedAccess() == SharingMode.NOSHARING) - nosharing = true; - - // Check if the required sharing mode is allowed by the current file open - - else if ( ( fstate.getSharedAccess() & params.getSharedAccess()) != params.getSharedAccess()) - nosharing = true; - - // Check if the caller wants exclusive access to the file - - else if ( params.getSharedAccess() == SharingMode.NOSHARING) - nosharing = true; - } - - // Check if the file allows shared access - - if ( nosharing == true) - { - if ( params.getPath().equals( "\\") == false) - throw new FileSharingException("File already open, " + params.getPath()); - } - - // Update the file sharing mode, if this is the first file open - - fstate.setSharedAccess( params.getSharedAccess()); - } } + else { + + // Create a file state for the path + + fstate = ctx.getStateTable().findFileState( params.getPath(), false, true); + } + + // Check if the current file open allows the required shared access + + boolean nosharing = false; + + // TEST + + if ( params.getAccessMode() == AccessMode.NTFileGenericExecute && params.getPath().toLowerCase().endsWith( ".exe") == false) { + + // DEBUG + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) { + logger.debug( "Execute access mode, path" + params.getPath()); + logger.debug( " Fstate=" + fstate); + } + + throw new AccessDeniedException("Invalid access mode"); + } + + if ( fstate.getOpenCount() > 0) { + + // Check for impersonation security level from the original process that opened the file + + if ( params.getSecurityLevel() == WinNT.SecurityImpersonation && params.getProcessId() == fstate.getProcessId()) + nosharing = false; + + // Check if the caller wants read access, check the sharing mode + // Check if the caller wants write access, check if the sharing mode allows write + + else if ( params.isReadOnlyAccess() && (fstate.getSharedAccess() & SharingMode.READ) != 0) + nosharing = false; + + // Check if the caller wants write access, check the sharing mode + + else if (( params.isReadWriteAccess() || params.isWriteOnlyAccess()) && (fstate.getSharedAccess() & SharingMode.WRITE) == 0) + { + // DEBUG + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Sharing mode disallows write access path=" + params.getPath()); + + // Access not allowed + + throw new AccessDeniedException( "Sharing mode (write)"); + } + + // Check if the file has been opened for exclusive access + + else if ( fstate.getSharedAccess() == SharingMode.NOSHARING) + nosharing = true; + + // Check if the required sharing mode is allowed by the current file open + + else if ( ( fstate.getSharedAccess() & params.getSharedAccess()) != params.getSharedAccess()) + nosharing = true; + + // Check if the caller wants exclusive access to the file + + else if ( params.getSharedAccess() == SharingMode.NOSHARING) + nosharing = true; + + } + + // Check if the file allows shared access + + if ( nosharing == true) + { + if ( params.getPath().equals( "\\") == false) { + + // DEBUG + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Sharing violation path=" + params.getPath() + ", sharing=0x" + Integer.toHexString(fstate.getSharedAccess())); + + // File is locked by another user + + throw new FileSharingException("File already open, " + params.getPath()); + } + } + + // Update the file sharing mode and process id, if this is the first file open + + fstate.setSharedAccess( params.getSharedAccess()); + fstate.setProcessId( params.getProcessId()); + + // DEBUG + + if ( logger.isDebugEnabled() && fstate.getOpenCount() == 0 && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Path " + params.getPath() + ", sharing=0x" + Integer.toHexString(params.getSharedAccess()) + ", PID=" + params.getProcessId()); } // Check if the node is a link node @@ -1508,13 +1566,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Debug - if (logger.isDebugEnabled()) - { - logger.debug("Opened network file: \n" + - " path: " + params.getPath() + "\n" + - " file open parameters: " + params + "\n" + - " network file: " + netFile); - } + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Opened network file: path=" + params.getPath() + " file open parameters=" + params + " network file=" + netFile); // Return the network file @@ -1524,7 +1577,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Open file - access denied, " + params.getFullPath()); // Convert to a filesystem access denied status @@ -1535,7 +1588,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Open file error", ex); // Convert to a general I/O exception @@ -1558,14 +1611,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Create the transaction beginWriteTransaction( sess); + ContentContext ctx = (ContentContext) tree.getContext(); try { // Get the device root - ContentContext ctx = (ContentContext) tree.getContext(); NodeRef deviceRootNodeRef = ctx.getRootNode(); - String path = params.getPath(); // If the state table is available then try to find the parent folder node for the new file @@ -1589,7 +1641,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file using cached noderef for path " + paths[0]); } } @@ -1626,6 +1678,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Save the file sharing mode, needs to be done before the open count is incremented fstate.setSharedAccess( params.getSharedAccess()); + fstate.setProcessId( params.getProcessId()); // Indicate that the file is open @@ -1639,20 +1692,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file, state=" + fstate); } } - // done - if (logger.isDebugEnabled()) - { - logger.debug("Created file: \n" + - " path: " + path + "\n" + - " file open parameters: " + params + "\n" + - " node: " + nodeRef + "\n" + - " network file: " + netFile); - } + // Debug + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Created file: path=" + path + " file open parameters=" + params + " node=" + nodeRef + " network file=" + netFile); return netFile; } @@ -1660,7 +1708,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file - access denied, " + params.getFullPath()); // Convert to a filesystem access denied status @@ -1671,7 +1719,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file - content I/O error, " + params.getFullPath()); // Convert to a filesystem disk full status @@ -1682,7 +1730,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file error", ex); // Convert to a general I/O exception @@ -1705,12 +1753,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // Create the transaction beginWriteTransaction( sess); + ContentContext ctx = (ContentContext) tree.getContext(); try { // get the device root - ContentContext ctx = (ContentContext) tree.getContext(); NodeRef deviceRootNodeRef = ctx.getRootNode(); String path = params.getPath(); @@ -1736,7 +1784,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create file using cached noderef for path " + paths[0]); } } @@ -1760,25 +1808,21 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Creaste folder, state=" + fstate); } } - // done - if (logger.isDebugEnabled()) - { - logger.debug("Created directory: \n" + - " path: " + path + "\n" + - " file open params: " + params + "\n" + - " node: " + nodeRef); - } + // Debug + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Created directory: path=" + path + " file open params=" + params + " node=" + nodeRef); } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create directory - access denied, " + params.getFullPath()); // Convert to a filesystem access denied status @@ -1789,7 +1833,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Create directory error", ex); // Convert to a general I/O exception @@ -1841,28 +1885,23 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa throw new DirectoryNotEmptyException( dir); } - // done - if (logger.isDebugEnabled()) - { - logger.debug("Deleted directory: \n" + - " directory: " + dir + "\n" + - " node: " + nodeRef); - } + // Debug + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Deleted directory: directory=" + dir + " node=" + nodeRef); } catch (FileNotFoundException e) { - // already gone - if (logger.isDebugEnabled()) - { - logger.debug("Deleted directory : \n" + - " directory: " + dir); - } + // Debug + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Delete directory - file not found, " + dir); } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete directory - access denied, " + dir); // Convert to a filesystem access denied status @@ -1873,7 +1912,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete directory", ex); // Convert to a general I/O exception @@ -1892,6 +1931,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa */ public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws IOException { + // Debug + + ContentContext ctx = (ContentContext) tree.getContext(); + + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILEIO)) + logger.debug("Flush file=" + file.getFullName()); + // Flush the file data file.flushFile(); @@ -1956,7 +2002,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa } catch ( Exception ex) { - if ( logger.isWarnEnabled()) + if ( logger.isWarnEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.warn("Error during delete on close, " + file.getFullName(), ex); } @@ -1982,7 +2028,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete on close - access denied, " + file.getFullName()); // Convert to a filesystem access denied exception @@ -2007,12 +2053,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if (logger.isDebugEnabled()) - { - logger.debug("Closed file: \n" + - " network file: " + file + "\n" + - " deleted on close: " + file.hasDeleteOnClose()); - } + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Closed file: network file=" + file + " delete on close=" + file.hasDeleteOnClose()); } /** @@ -2048,15 +2090,16 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa ctx.getStateTable().removeFileState(name); } - // done - if (logger.isDebugEnabled()) - logger.debug("Deleted file: " + name + ", node: " + nodeRef); + // Debug + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) + logger.debug("Deleted file: " + name + ", node=" + nodeRef); } catch (NodeLockedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete file - access denied (locked)"); // Convert to a filesystem access denied status @@ -2067,7 +2110,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete file - access denied"); // Convert to a filesystem access denied status @@ -2078,7 +2121,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) logger.debug("Delete file error", ex); // Convert to a general I/O exception @@ -2102,12 +2145,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa beginWriteTransaction( sess); + // Get the device context + + ContentContext ctx = (ContentContext) tree.getContext(); + try { - // Get the device context - - ContentContext ctx = (ContentContext) tree.getContext(); - // Get the file/folder to move NodeRef nodeToMoveRef = getNodeForPath(tree, oldName); @@ -2156,7 +2199,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug(" Found rename state, relinking, " + renState); // Relink the new version of the file data to the previously renamed node so that it @@ -2186,7 +2229,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug(" Found delete on close state, restore and relink, " + renState); // Restore the deleted node so we can relink the new version to the old history/properties @@ -2195,7 +2238,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug(" Found archived node + " + archivedNode); if ( archivedNode != null && getNodeService().exists( archivedNode)) @@ -2206,7 +2249,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug(" Restored node " + restoredNode); if ( restoredNode != null) @@ -2232,7 +2275,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug(" Swapped content to restored node, delete " + oldName + ", nodeRef=" + nodeToMoveRef); // Link the node ref for the associated rename state @@ -2295,7 +2338,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug("Added Temporary aspect to renamed file " + newName); } @@ -2315,14 +2358,14 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug("Removed Temporary aspect from renamed file " + newName); } // DEBUG - if ( logger.isDebugEnabled()) - logger.debug("Renamed file: from: " + oldName + " to: " + newName); + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) + logger.debug("Renamed file: from=" + oldName + " to=" + newName); } else { @@ -2332,15 +2375,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) - logger.debug("Moved file: from: " + oldName + " to: " + newName); + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) + logger.debug("Moved file: from=" + oldName + " to=" + newName); } // Check if we renamed a file, if so then cache the rename details for a short period // in case another file renamed to the old name. MS Word uses renames to move a new // version of a document into place so we need to reconnect the version history. - if ( !cifsHelper.isDirectory(nodeToMoveRef)) + if ( !cifsHelper.isDirectory(nodeToMoveRef) && sameFolder == true) { // Get or create a new file state for the old file path @@ -2369,7 +2412,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) { logger.debug("Cached rename state for " + oldName + ", state=" + fstate); logger.debug(" new name " + newName + ", state=" + newState); @@ -2379,14 +2422,14 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if (logger.isDebugEnabled()) - logger.debug("Moved node: from: " + oldName + " to: " + newName); + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) + logger.debug("Moved node: from=" + oldName + " to=" + newName); } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug("Rename file - access denied, " + oldName); // Convert to a filesystem access denied status @@ -2397,7 +2440,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug("Rename file", ex); // Convert to an filesystem access denied exception @@ -2408,7 +2451,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) logger.debug("Rename file", ex); // Convert to a general I/O exception @@ -2428,12 +2471,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa */ public void setFileInformation(SrvSession sess, TreeConnection tree, String name, FileInfo info) throws IOException { + // Get the device context + + ContentContext ctx = (ContentContext) tree.getContext(); + try { - // Get the device context - - ContentContext ctx = (ContentContext) tree.getContext(); - // Check if pseudo files are enabled if ( hasPseudoFileInterface(ctx) && @@ -2496,7 +2539,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Set deleteOnClose=true file=" + name); } @@ -2520,7 +2563,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Set creationDate=" + createDate + " file=" + name); } @@ -2544,7 +2587,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa // DEBUG - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Set modifyDate=" + modifyDate + " file=" + name); } } @@ -2552,7 +2595,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Set file information - access denied, " + name); // Convert to a filesystem access denied status @@ -2563,7 +2606,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Debug - if ( logger.isDebugEnabled()) + if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO)) logger.debug("Open file error", ex); // Convert to a general I/O exception @@ -2587,13 +2630,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa file.truncateFile(size); - // done - if (logger.isDebugEnabled()) - { - logger.debug("Truncated file: \n" + - " network file: " + file + "\n" + - " size: " + size); - } + // Debug + + ContentContext ctx = (ContentContext) tree.getContext(); + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILEIO)) + logger.debug("Truncated file: network file=" + file + " size=" + size); } /** @@ -2639,17 +2681,14 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa count = 0; } - // done - if (logger.isDebugEnabled()) - { - logger.debug("Read bytes from file: \n" + - " network file: " + file + "\n" + - " buffer size: " + buffer.length + "\n" + - " buffer pos: " + bufferPosition + "\n" + - " size: " + size + "\n" + - " file offset: " + fileOffset + "\n" + - " bytes read: " + count); - } + // Debug + + ContentContext ctx = (ContentContext) tree.getContext(); + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILEIO)) + logger.debug("Read bytes from file: network file=" + file + " buffer size=" + buffer.length + " buffer pos=" + bufferPosition + + " size=" + size + " file offset=" + fileOffset + " bytes read=" + count); + return count; } @@ -2712,15 +2751,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa file.writeFile(buffer, size, bufferOffset, fileOffset); - // done - if (logger.isDebugEnabled()) - { - logger.debug("Wrote bytes to file: \n" + - " network file: " + file + "\n" + - " buffer size: " + buffer.length + "\n" + - " size: " + size + "\n" + - " file offset: " + fileOffset); - } + // Debug + + ContentContext ctx = (ContentContext) tree.getContext(); + + if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILEIO)) + logger.debug("Wrote bytes to file: network file=" + file + " buffer size=" + buffer.length + " size=" + size + " file offset=" + fileOffset); + return size; } diff --git a/source/java/org/alfresco/filesys/repo/ContentNetworkFile.java b/source/java/org/alfresco/filesys/repo/ContentNetworkFile.java index 4d6671b618..de14cd1527 100644 --- a/source/java/org/alfresco/filesys/repo/ContentNetworkFile.java +++ b/source/java/org/alfresco/filesys/repo/ContentNetworkFile.java @@ -47,6 +47,7 @@ import org.alfresco.repo.content.encoding.ContentCharsetFinder; import org.alfresco.repo.content.filestore.FileContentReader; import org.alfresco.service.cmr.repository.ContentAccessor; import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; @@ -426,25 +427,38 @@ public class ContentNetworkFile extends NodeRefNetworkFile public void truncateFile(long size) throws IOException { - // If the content data channel has not been opened yet and the requested size is zero - // then this is an open for overwrite so the existing content data is not copied - - if ( hasContent() == false && size == 0L) - { - // Open content for overwrite, no need to copy existing content data + try { + // If the content data channel has not been opened yet and the requested size is zero + // then this is an open for overwrite so the existing content data is not copied - openContent(true, true); - } - else - { - // Normal open for write - - openContent(true, false); + if ( hasContent() == false && size == 0L) + { + // Open content for overwrite, no need to copy existing content data + + openContent(true, true); + } + else + { + // Normal open for write + + openContent(true, false); - // Truncate or extend the channel - - channel.truncate(size); - } + // Truncate or extend the channel + + channel.truncate(size); + } + } + catch ( ContentIOException ex) { + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Error opening file " + getFullName() + " for write", ex); + + // Convert to a file server I/O error + + throw new DiskFullException("Failed to open " + getFullName() + " for write"); + } // Set modification flag @@ -477,9 +491,22 @@ public class ContentNetworkFile extends NodeRefNetworkFile public void writeFile(byte[] buffer, int length, int position, long fileOffset) throws IOException { - // Open the channel for writing - - openContent(true, false); + try { + // Open the channel for writing + + openContent(true, false); + } + catch ( ContentIOException ex) { + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Error opening file " + getFullName() + " for write", ex); + + // Convert to a file server I/O error + + throw new DiskFullException("Failed to open " + getFullName() + " for write"); + } // Write to the channel diff --git a/source/java/org/alfresco/filesys/repo/ContentSearchContext.java b/source/java/org/alfresco/filesys/repo/ContentSearchContext.java index 4aa6b7d80c..02d27838c0 100644 --- a/source/java/org/alfresco/filesys/repo/ContentSearchContext.java +++ b/source/java/org/alfresco/filesys/repo/ContentSearchContext.java @@ -34,6 +34,7 @@ import org.alfresco.jlan.server.filesys.FileType; import org.alfresco.jlan.server.filesys.SearchContext; import org.alfresco.jlan.server.filesys.pseudo.PseudoFile; import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -76,6 +77,10 @@ public class ContentSearchContext extends SearchContext private String m_relPath; + // Keep track of the last file name returned for fast restartAt processing + + private String m_lastFileName; + /** * Class constructor * @@ -111,10 +116,18 @@ public class ContentSearchContext extends SearchContext public String toString() { StringBuilder sb = new StringBuilder(60); - sb.append("ContentSearchContext") - .append("[ searchStr=").append(getSearchString()) - .append(", resultCount=").append(results.size()) - .append("]"); + + sb.append("[ContentSearchContext searchStr="); + sb.append(getSearchString()); + sb.append(", resultCount="); + sb.append(results.size()); + sb.append(", pseudoList="); + if ( pseudoList != null) + sb.append( pseudoList.numberOfFiles()); + else + sb.append("NULL"); + sb.append("]"); + return sb.toString(); } @@ -205,17 +218,46 @@ public class ContentSearchContext extends SearchContext } } - // Get the next file info from the node search - - NodeRef nextNodeRef = results.get(index); + // Return the next available file information for a real file/folder try { - // Get the file information and copy across to the callers file info - - ContentFileInfo nextInfo = cifsHelper.getFileInformation(nextNodeRef, ""); - info.copyFrom(nextInfo); + // Loop until we get a valid node, might have been deleted since the initial folder search + + ContentFileInfo nextInfo = null; + + while ( nextInfo == null && index < results.size()) + { + // Get the next node from the search + + NodeRef nextNodeRef = results.get(index); + try { + + // Get the file information and copy across to the callers file info + + nextInfo = cifsHelper.getFileInformation(nextNodeRef, ""); + info.copyFrom(nextInfo); + } + catch ( InvalidNodeRefException ex) { + + // Log a warning + + if ( logger.isWarnEnabled()) + logger.warn("Noderef " + nextNodeRef + " no longer valid, ignoring"); + + // Update the node index, node no longer exists, try the next node in the search + + index++; + resumeId++; + } + } + + // Check if we have finished returning file info + + if ( nextInfo == null) + return false; + // Generate a file id for the current file StringBuilder pathStr = new StringBuilder( m_relPath); @@ -243,6 +285,10 @@ public class ContentSearchContext extends SearchContext else info.setFileType( FileType.RegularFile); + // Keep track of the last file name returned + + m_lastFileName = info.getFileName(); + // Indicate that the file information is valid return true; @@ -313,6 +359,10 @@ public class ContentSearchContext extends SearchContext // Get the file information and copy across to the callers file info FileInfo nextInfo = cifsHelper.getFileInformation(nextNodeRef, ""); + + // Keep track of the last file name returned + + m_lastFileName = nextInfo.getFileName(); // Indicate that the file information is valid @@ -360,6 +410,17 @@ public class ContentSearchContext extends SearchContext } } + // Check if the resume file name is the last file returned, no need to reposition the file index + + if ( m_lastFileName != null && info.getFileName().equalsIgnoreCase( m_lastFileName)) { + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Fast search restart - " + m_lastFileName); + return true; + } + // Check if the resume file is in the main file list if ( results != null) diff --git a/source/java/org/alfresco/filesys/repo/MSOfficeContentNetworkFile.java b/source/java/org/alfresco/filesys/repo/MSOfficeContentNetworkFile.java index ce21966123..eabccdc860 100644 --- a/source/java/org/alfresco/filesys/repo/MSOfficeContentNetworkFile.java +++ b/source/java/org/alfresco/filesys/repo/MSOfficeContentNetworkFile.java @@ -132,7 +132,7 @@ public class MSOfficeContentNetworkFile extends ContentNetworkFile { // Buffer the write, looks like a file open update. Do not buffer zero length writes. - if ( length == 0) { + if ( length != 0) { byte[] data = new byte[ length]; System.arraycopy(buffer, position, data, 0, length); diff --git a/source/java/org/alfresco/filesys/state/FileState.java b/source/java/org/alfresco/filesys/state/FileState.java index 76facf3b61..9a940b3d66 100644 --- a/source/java/org/alfresco/filesys/state/FileState.java +++ b/source/java/org/alfresco/filesys/state/FileState.java @@ -75,9 +75,10 @@ public class FileState private int m_openCount; - // Sharing mode + // Sharing mode and PID of first process to open the file private int m_sharedAccess = SharingMode.READWRITE + SharingMode.DELETE; + private int m_pid = -1; // File lock list, allocated once there are active locks on this file @@ -203,6 +204,16 @@ public class FileState return m_sharedAccess; } + /** + * Return the PID of the first process to open the file, or -1 if the file is not open + * + * @return int + */ + public final int getProcessId() + { + return m_pid; + } + /** * Check if there are active locks on this file * @@ -279,6 +290,11 @@ public class FileState else m_openCount--; + // Clear the PID if the file is no longer open + + if ( m_openCount == 0) + m_pid = -1; + return m_openCount; } @@ -430,6 +446,17 @@ public class FileState m_sharedAccess = mode; } + /** + * Set the PID of the process opening the file + * + * @param pid int + */ + public final void setProcessId(int pid) + { + if ( getOpenCount() == 0) + m_pid = pid; + } + /** * Set the file path * @@ -703,6 +730,8 @@ public class FileState str.append(getFileStatus()); str.append(":Opn="); str.append(getOpenCount()); + str.append("/"); + str.append(getProcessId()); str.append(",Expire="); str.append(getSecondsToExpire(System.currentTimeMillis()));