VirtualFileSystem.cpp
资源名称:warftpd.zip [点击查看]
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:43k
源码类别:
Ftp客户端
开发平台:
Visual C++
- // VirtualFileSystem.cpp : implementation file
- //
- #include "stdafx.h"
- // For now, we don't support non-daemon programs
- //#include "WarSoftware.h"
- #include "WarDaemon.h"
- #include "WarFsys.h"
- #include "VfFSys.h"
- #include "UnixFsysTypes.h"
- #include "FsysSecurity.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CVirtualFileSystem
- CLinkedList CVirtualFileSystem::m_FreeThreads;
- CLinkedList CVirtualFileSystem::m_BusyThreads;
- CVirtualFileSystem::CVirtualFileSystem()
- {
- }
- CVirtualFileSystem::~CVirtualFileSystem()
- {
- }
- void CVirtualFileSystem::Shutdown()
- {
- // Clean up. Only one object pr. process, so we can do it right :-)
- CLinkedList MyList;
- CWinThread *pThread;
- MyList = m_FreeThreads;
- MyList += m_BusyThreads;
- while(pThread = (CWinThread *) MyList.GetAndDeleteFirst())
- {
- pThread->AssertValid();
- if (!::PostThreadMessage(pThread->m_nThreadID, FSM_QUIT, 0, 0))
- {
- CLog::GetLog()->LogMsg(LOGF_ERROR,"CVirtualFileSystem::Shutdown() - PostThreadMessage failed: %s",
- GetLastErrorText());
- // Patch. Just kill the linked lists..
- while(m_FreeThreads.GetAndDeleteFirst());
- while(m_BusyThreads.GetAndDeleteFirst());
- }
- }
- while(m_FreeThreads.GetItemCount() || m_BusyThreads.GetItemCount())
- Sleep(100);
- }
- BEGIN_MESSAGE_MAP(CVirtualFileSystem, CWnd)
- //{{AFX_MSG_MAP(CVirtualFileSystem)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- //}}AFX_MSG_MAP
- ON_MESSAGE(FSM_CALLBACK, mhCallback)
- ON_MESSAGE(FSM_CREATEFILE, mhCreateFile)
- ON_MESSAGE(FSM_CREATEUSER, mhCreate)
- ON_MESSAGE(FSM_CHDIR, mhChdir)
- ON_MESSAGE(FSM_CHMOD, mhChmod)
- ON_MESSAGE(FSM_PRPCMDLINE, mhPreperePath)
- ON_MESSAGE(FSM_LIST, mhList)
- ON_MESSAGE(FSM_WLST, mhWlist)
- ON_MESSAGE(FSM_CLOSEFILE, mhCloseFile)
- ON_MESSAGE(FSM_FSYSSTAT, mhFsysstat)
- ON_MESSAGE(FSM_CREATEDIR, mhCreateDir)
- ON_MESSAGE(FSM_DELEDIR, mhDeleteDir)
- ON_MESSAGE(FSM_DELEFILE, mhDeleteFile)
- ON_MESSAGE(FSM_DELE, mhDeleteGeneric)
- ON_MESSAGE(FSM_LINK, mhLinkFile)
- ON_MESSAGE(FSM_MOVE, mhMoveFile)
- ON_MESSAGE(FSM_QUIT, mhQuit)
- ON_MESSAGE(FSM_STAT, mhStat)
- END_MESSAGE_MAP()
- // Get a free worker thread. Then, mark it as busy.
- // If pTherad is <> NULL, release the thread
- CWinThread *CVirtualFileSystem::GetThread(CWinThread *pTherad, HWND hWnd)
- {
- static CCriticalSection Lock;
- Lock.Lock();
- if (pTherad == NULL)
- {
- if ((pTherad = (CWinThread *)m_FreeThreads.GetAndDeleteFirst()) == NULL)
- {
- CFsysThread *pThreadObj = new CFsysThread;
- pThreadObj->m_CallbackWin = hWnd;
- if ((pTherad = AfxBeginThread(CFsysThread::EntryPoint, (LPVOID)pThreadObj)) == NULL)
- delete pThreadObj;
- else
- {
- pThreadObj->m_Lock.Lock();
- pThreadObj->m_Lock.Unlock();
- }
- }
- if (pTherad)
- {
- // Wait for the thread to initialize
- m_FreeThreads.DeletePtr((LPVOID)pTherad);
- m_BusyThreads.AddLast((LPVOID)pTherad);
- }
- }
- else
- {
- m_BusyThreads.DeletePtr(pTherad);
- m_FreeThreads.AddLast((LPVOID)pTherad);
- }
- Lock.Unlock();
- return pTherad;
- }
- // Call a worker thread and pass the request on
- LONG CVirtualFileSystem::ProcessRequest(int Type, WPARAM wParam, LPARAM lParam)
- {
- CWinThread *pThrd = GetThread(NULL,m_hWnd);
- if (!pThrd)
- return FALSE;
- ::PostThreadMessage(pThrd->m_nThreadID, Type, wParam, lParam);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CVirtualFileSystem message handlers
- LONG CVirtualFileSystem::mhCallback( WPARAM wParam, LPARAM lParam)
- {
- CUserFsys *pFsys = (CUserFsys *)wParam;
- pFsys->OnCallback(lParam);
- return 0;
- }
- LONG CVirtualFileSystem::mhCreateFile( WPARAM wParam, LPARAM lParam)
- {
- CString Roots = (LPCSTR)lParam;
- return ProcessRequest(FSM_CREATEFILE, wParam, (LPARAM)(LPCSTR)Roots);
- }
- LONG CVirtualFileSystem::mhCreate( WPARAM wParam, LPARAM lParam)
- {
- CString Roots = (LPCSTR)lParam;
- return ProcessRequest(FSM_CREATEUSER, wParam, (LPARAM)(LPCSTR)Roots);
- }
- LONG CVirtualFileSystem::mhChdir( WPARAM wParam, LPARAM lParam)
- {
- CString Roots = (LPCSTR)lParam;
- return ProcessRequest(FSM_CHDIR, wParam, (LPARAM)(LPCSTR)Roots);
- }
- LONG CVirtualFileSystem::mhChmod( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_CHMOD, wParam, NULL);
- }
- LONG CVirtualFileSystem::mhPreperePath( WPARAM wParam, LPARAM lParam)
- {
- CString Roots = (LPCSTR)lParam;
- return ProcessRequest(FSM_PRPCMDLINE, wParam, (LPARAM)(LPCSTR)Roots);
- }
- LONG CVirtualFileSystem::mhList( WPARAM wParam, LPARAM lParam)
- {
- CString Roots = (LPCSTR)lParam;
- return ProcessRequest(FSM_LIST, wParam, (LPARAM)(LPCSTR)Roots);
- }
- LONG CVirtualFileSystem::mhWlist( WPARAM wParam, LPARAM lParam)
- {
- CString Path = (LPCSTR)lParam;
- return ProcessRequest(FSM_WLST, wParam, (LPARAM)(LPCSTR)Path);
- }
- LONG CVirtualFileSystem::mhCloseFile( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_CLOSEFILE, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhFsysstat( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_FSYSSTAT, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhCreateDir( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_CREATEDIR, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhDeleteDir( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_DELEDIR, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhDeleteFile( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_DELEFILE, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhDeleteGeneric( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_DELE, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhLinkFile( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_LINK, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhMoveFile( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_MOVE, wParam, lParam);
- }
- LONG CVirtualFileSystem::mhQuit( WPARAM wParam, LPARAM lParam)
- {
- Shutdown();
- return TRUE;
- }
- LONG CVirtualFileSystem::mhStat( WPARAM wParam, LPARAM lParam)
- {
- return ProcessRequest(FSM_STAT, wParam, lParam);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CFsysThread
- int CFsysThread::m_NumThreadsStarted = 0;
- CFsysThread::CFsysThread()
- {
- m_Lock.Lock();
- m_SeqNo = 0;
- m_CallbackWin = NULL;
- }
- CFsysThread::~CFsysThread()
- {
- }
- void CFsysThread::LogMsg(int flag, LPCSTR Format, ...)
- {
- if (!ShouldLog(CLog::GetLog(), flag))
- return;
- {
- CString cBuf;
- ASSERT(AfxIsValidString(Format, FALSE));
- cBuf.Format("VfSys::%s: %s", m_pFsys->m_Name, Format);
- va_list argList;
- va_start(argList, Format);
- CLog::GetLog()->LogMsgV(flag, cBuf, argList);
- va_end(argList);
- }
- }
- UINT CFsysThread::EntryPoint(LPVOID pParam)
- {
- CFsysThread *pMe = (CFsysThread *)pParam;
- return pMe->Process();
- }
- UINT CFsysThread::Process()
- {
- // Set up a message queue
- MSG msg;
- PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);
- BOOL Rval;
- m_SeqNo = ++m_NumThreadsStarted;
- // Signal that we are ready
- m_Lock.Unlock();
- // Go into message loop
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"CFsysThread::Process() Thread #%d (0x%08x) starting up.", m_SeqNo, AfxGetThread());
- while(GetMessage(&msg,NULL,0,0) == TRUE)
- {
- CUserFsys *pFsys = (CUserFsys *)msg.wParam;
- if (pFsys)
- {
- pFsys->m_FsysErrno = 0;
- pFsys->m_DOSErrno = 0;
- m_pFsys = pFsys;
- }
- switch(msg.message)
- {
- case FSM_QUIT:
- case WM_QUIT:
- goto done;
- case FSM_CREATEFILE:
- Rval = DoCreateFile(pFsys->m_FsysPath1);
- break;
- case FSM_CREATEUSER:
- Rval = DoCreateUser(pFsys->m_FsysPath1);
- break;
- case FSM_CHDIR:
- Rval = DoChDirUser(pFsys->m_FsysPath1);
- break;
- case FSM_CHMOD:
- Rval = DoChmod(pFsys->m_Args);
- break;
- case FSM_PRPCMDLINE:
- Rval = DoPrepereUserCmdLine(pFsys->m_FsysPath1);
- break;
- case FSM_LIST:
- Rval = DoList(pFsys->m_FsysPath1);
- break;
- case FSM_CLOSEFILE:
- Rval = TRUE;
- DoCloseFile(*(SMEM *)&msg.lParam);
- break;
- case FSM_WLST:
- Rval = DoWlist(pFsys->m_FsysPath1);
- break;
- case FSM_FSYSSTAT:
- Rval = DoFsysStat();
- break;
- case FSM_CREATEDIR:
- Rval = DoCreateDirectory(pFsys->m_FsysPath1);
- break;
- case FSM_DELEDIR:
- Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_DIR);
- break;
- case FSM_DELEFILE:
- Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_FILE);
- break;
- case FSM_DELE:
- Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_DIR | DELE_FILE);
- break;
- case FSM_LINK:
- Rval = DoCreateLink(pFsys->m_FsysPath1, pFsys->m_FsysPath2);
- break;
- case FSM_MOVE:
- Rval = DoMoveFile(pFsys->m_FsysPath1, pFsys->m_FsysPath2);
- break;
- case FSM_STAT:
- Rval = DoStat(pFsys->m_FsysPath1);
- break;
- default:
- CLog::GetLog()->LogMsg(LOGF_WARNINGS,"CFsysThread::Process() - Got unknown message %u", msg.message);
- pFsys->m_FsysErrno = FSE_UNKNOWN_CALL;
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)pFsys, 0);
- }
- if (!Rval)
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)msg.wParam, 0);
- // Release the thread
- CVirtualFileSystem::GetThread(AfxGetThread(), NULL);
- }
- done:
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"CFsysThread::Process() Thread #%d shutting down.", m_SeqNo);
- CVirtualFileSystem::m_FreeThreads.DeletePtr((LPVOID)AfxGetThread());
- delete this;
- return 0;
- }
- BOOL CFsysThread::ParseRootpath(LPCSTR RootPath, CString& Name, CString& LinkPath)
- {
- CString cBuf = RootPath;
- LPSTR p = cBuf.GetBuffer(1);
- p = strchr(p, ',');
- if (p)
- *p++ = 0;
- cBuf.ReleaseBuffer();
- LinkPath = cBuf;
- Name = p ? p : "";
- return TRUE;
- }
- // Scan a path, starting at the user root...
- BOOL CFsysThread::ScanPath(LPCSTR Path, BOOL FullScanToPath, BOOL Recursive, BOOL Force, BOOL DoLock)
- {
- if (DoLock)
- pLock->WriteLock();
- DIR_NODE *pRoot = GetRootNode();
- DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(pRoot->Son);
- while(pDir)
- {
- if (pDir->FileNode.LinkTo)
- {
- CString ParsedPath = Path;
- ParsePath(ParsedPath);
- CString MyPath = pDir->FileNode.LinkTo;
- if (!MyPath.IsEmpty() && (MyPath[MyPath.GetLength() -1] == '/'))
- MyPath.ReleaseBuffer(MyPath.GetLength() -1);
- MyPath += ParsedPath;
- ::ScanPath(MyPath, FullScanToPath, Recursive, Force);
- }
- pDir = (DIR_NODE *)pSmem->__Ptr(pRoot->FileNode.Next);
- }
- if (DoLock)
- pLock->UnlockWrite();
- return TRUE;
- }
- DIR_NODE *CFsysThread::GetRootNode()
- {
- SMEM *pSM = (SMEM *)&m_pFsys->m_FsysLparam;
- DIR_NODE *pRoot = (DIR_NODE *)pSmem->__Ptr(*pSM);
- return pRoot;
- }
- BOOL CFsysThread::ParsePath(CString& OrigPath)
- {
- CString MyPath = OrigPath;
- int cnt = 0;
- LPCSTR Path = OrigPath;
- if (*Path != '/')
- {
- // Path is relative to
- CString cBuf = m_pFsys->m_CWD;
- if (cBuf.GetLength() && (cBuf[cBuf.GetLength() -1] != '/'))
- cBuf += '/';
- cBuf += Path;
- MyPath = OrigPath = cBuf;
- Path = OrigPath;
- }
- char *Buf = MyPath.GetBuffer(1);
- while(*Path)
- {
- if (*Path == '/')
- {
- // /C/.. /C/./any /C/any/. /C/any/../.any /C/any..
- if (Path[1] == '.')
- {
- if (!Path[2] || (Path[2] == '/'))
- {
- // /C/any/. style. Just ignore
- Path += 2;
- continue;
- }
- if (Path[2] == '.')
- {
- if (!Path[3] || (Path[3] == '/'))
- {
- // /C/any/.. /C/any/../test style. Move back one
- if (cnt == 0)
- {
- LogMsg(LOGF_DEBUG,"RealPath(%s) - invalid ../ ", OrigPath);
- return FALSE;
- }
- while(--cnt && (Buf[cnt] != '/'))
- {
- ASSERT(cnt >= 0);
- }
- Path += 3;
- continue;
- }
- }
- }
- }
- // Default
- Buf[cnt++] = *Path++;
- }
- if (cnt == 0)
- OrigPath = "/"; // Never move beoind /
- else
- {
- Buf[cnt] = 0;
- OrigPath = Buf;
- }
- return TRUE;
- }
- BOOL CFsysThread::UserHasPermission(DWORD Perms, DWORD PermWanted)
- {
- if (PermWanted & NODE_EXEC)
- {
- if (!(Perms & (NODE_OEXEC | NODE_GEXEC | NODE_AEXEC)))
- return FALSE; // No permissions
- }
- if (PermWanted & NODE_READ)
- {
- if (!(Perms & (NODE_OREAD | NODE_GREAD | NODE_AREAD)))
- return FALSE; // No permissions
- }
- if (PermWanted & NODE_WRITE)
- {
- if (!(Perms & (NODE_0WRITE | NODE_GWRITE | NODE_AWRITE)))
- return FALSE; // No permissions
- }
- if (PermWanted & NODE_HIDE)
- {
- if (!(Perms & (NODE_OHIDE | NODE_GHIDE | NODE_AHIDE)))
- return FALSE; // No permissions
- }
- if (PermWanted & NODE_FREE)
- {
- if (!(Perms & (NODE_OFREE | NODE_GFREE | NODE_AFREE)))
- return FALSE; // No permissions
- }
- return TRUE;
- }
- // Check if a user has a desired permission to a node
- // Note: pDir can be any node type
- BOOL CFsysThread::UserHasPermission(DIR_NODE *pDir, DWORD Perm)
- {
- if (m_pFsys->m_IsAdmin || m_pFsys->m_IsSystem)
- return TRUE;
- if (pDir->FileNode.LinkTo)
- {
- SMEM smDir;
- FindNodeFromPath(smDir, pDir->FileNode.LinkTo);
- DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
- if (pLinkTo)
- return UserHasPermission(pLinkTo, Perm);
- LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
- return FALSE;
- }
- int Mask = S_IRWXO;
- int Perms = pDir->FileNode.Perms;
- if (pDir->FileNode.User == m_pFsys->m_User)
- Mask |= S_IRWXU;
- if (pDir->FileNode.Class == m_pFsys->m_Class)
- Mask |= S_IRWXG;
- BOOL HasAccess = UserHasPermission(Perms & Mask, Perm);
- if (!HasAccess)
- {
- // Check for additional permissions
- USER *pUsers = (USER *)pSmem->__Ptr(pDir->FileNode.MoreUsers);
- if (pUsers)
- {
- Mask |= S_IRWXG;
- for(int i = 0; pUsers[i] != INVALID_USER_VALUE; i++)
- {
- if ((pUsers[i] == m_pFsys->m_User) || (pUsers[i] == m_pFsys->m_Class))
- {
- HasAccess = UserHasPermission(Perms & Mask, Perm);
- break;
- }
- }
- }
- }
- return HasAccess;
- }
- // Check if the user has permission to a path.
- // If psmNode != NULL, return the destination node on success
- BOOL CFsysThread::CheckPermissions(LPCSTR Path, DWORD ReqType, DWORD Perm, SMEM *psmNode)
- {
- DIR_NODE *pRoot = GetRootNode();
- SMEM smDir = pRoot->Son;
- CPathArray PathArray;
- PathArray.ParsePathToArray(Path);
- BOOL PermissionToCreate = FALSE;
- DIR_NODE *pDir = NULL;
- for(int Index = 0; Index <= PathArray.GetUpperBound(); Index++)
- {
- smDir = Index ? FindNode(smDir, PathArray[Index]) : pRoot->Son;
- if (!smDir)
- {
- if (psmNode)
- {
- psmNode = 0;
- }
- return PermissionToCreate;
- }
- pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- if (pDir->FileNode.Perms & NODE_LINK)
- {
- // Follow link
- if (!FindNodeFromPath(smDir, pDir->FileNode.LinkTo))
- {
- LogMsg(LOGF_WARNINGS,"CFsysThread::CheckPermissions() - Unresolved soft link: '%s'", pDir->FileNode.LinkTo);
- return FALSE;
- }
- pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- }
- if (pDir->FileNode.Perms & NODE_DIR)
- {
- // Check execute permission
- if (!UserHasPermission(pDir, NODE_EXEC))
- return FALSE;
- }
- if (Index == (PathArray.GetUpperBound() - 1))
- {
- // Special case. If the user want to create something, check the
- // permissions on this level.
- if ((Perm & NODE_WRITE) && (pDir->FileNode.Perms & NODE_DIR))
- {
- PermissionToCreate = UserHasPermission(pDir, NODE_EXEC | NODE_WRITE);
- }
- }
- }
- ASSERT(pDir != NULL);
- if (ReqType && !(pDir->FileNode.Perms & ReqType))
- return FALSE;
- if (!UserHasPermission(pDir, Perm))
- return FALSE;
- if (psmNode)
- *psmNode = smDir;
- return TRUE;
- }
- // Look for the name in the directory, and in
- // hard linked subdirs
- SMEM CFsysThread::FindNode(SMEM& smDir, LPCSTR Name)
- {
- DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- SMEM Rval;
- Rval = 0;
- if (!pDir)
- return Rval;
- while(!pDir->FileNode.Name && pDir->FileNode.LinkTo)
- {
- SMEM smLinkDir;
- FindNodeFromPath(smLinkDir, pDir->FileNode.LinkTo);
- DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smLinkDir);
- if (pLinkTo)
- {
- pDir = pLinkTo;
- }
- else
- {
- LogMsg(LOGF_WARNINGS,
- "CFsysThread::FindNode(%s) - Broken link detected in file system (%s).",
- Name, pDir->FileNode.LinkTo);
- return Rval;
- }
- }
- FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
- Rval = pDir->Son;
- while(pNode)
- {
- if (!pNode->Name && pNode->LinkTo)
- {
- SMEM smLinkDir;
- FindNodeFromPath(smLinkDir, pNode->LinkTo);
- DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
- if (pLinkTo)
- {
- SMEM smTest = FindNode(smLinkDir, Name);
- if (smTest)
- return smTest;
- }
- else
- {
- LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
- }
- }
- else if (pNode->Name && !stricmp(pNode->Name, Name))
- break;
- Rval = pNode->Next;
- pNode = (FILE_NODE *)pSmem->__Ptr(Rval);
- }
- return Rval;
- }
- ///////////////////////////////////////////////////////////////////////////
- // Build a CFileInfoList
- BOOL CFsysThread::BldFileInfoList(CFileList& FileList, LPCSTR Path, BOOL ListDir)
- {
- CString MyPath = Path;
- ParsePath(MyPath);
- CString Pattern = "*", COrigPath = MyPath;
- LPSTR pp = strrchr(MyPath.GetBuffer(1), '/'), p = pp;
- LogMsg(LOGF_DEBUG,"BldFileInfoList() INFO: Path = '%s' and %s", Path, ListDir ? "DIR" : "FILE");
- if (ListDir)
- {
- if (p && !strpbrk(p, "*?"))
- {
- if (AddFileInfoListPath(FileList, MyPath, Pattern))
- return TRUE;
- }
- }
- if (p && (p >= pp))
- {
- *p++ = 0;
- Pattern = p;
- }
- else
- {
- LogMsg(LOGF_DEBUG,"BldFileInfoList() - Cannot list '%s'.", Path);
- return FALSE;
- }
- AddFileInfoListPath(FileList, MyPath, Pattern);
- return TRUE;
- }
- int CFsysThread::AddFileInfoListPath(CFileList& FileList, LPCSTR Path, LPCSTR Pattern)
- {
- SMEM smNode;
- // Get the dir to list
- if (!CheckPermissions(Path, NODE_DIR, NODE_READ, &smNode))
- {
- LogMsg(LOGF_DEBUG,"AddFileInfoListPath() - Permission denied on '%s'.", Path);
- return FALSE;
- }
- return AddFileInfoListPath(FileList, smNode, Pattern);
- }
- int CFsysThread::AddFileInfoListPath(CFileList& FileList, SMEM smDir, LPCSTR Pattern)
- {
- int Count = 0;
- DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- SMEM Rval;
- Rval = 0;
- if (!pDir)
- return Count;
- while(!pDir->FileNode.Name && pDir->FileNode.LinkTo)
- {
- SMEM smLinkDir;
- FindNodeFromPath(smLinkDir, pDir->FileNode.LinkTo);
- DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smLinkDir);
- if (pLinkTo)
- {
- pDir = pLinkTo;
- }
- }
- FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
- if (!pNode)
- LogMsg(LOGF_DEBUG,"AddFileInfoListPath() - pNode is NULL. Nothing to list...");
- while(pNode)
- {
- if (!pNode->Name && pNode->LinkTo)
- {
- SMEM smLinkDir;
- FindNodeFromPath(smLinkDir, pNode->LinkTo);
- DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
- if (pLinkTo)
- {
- Count += AddFileInfoListPath(FileList, smLinkDir, Pattern);
- }
- else
- {
- LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
- }
- }
- else if (pNode->Name
- && PatternMatchesName(pNode->Name, Pattern)
- && (m_pFsys->m_IsAdmin || !UserHasPermission(pNode->Perms, NODE_HIDE)))
- {
- ++Count;
- FileList.Add(pNode);
- }
- Rval = pNode->Next;
- pNode = (FILE_NODE *)pSmem->__Ptr(Rval);
- }
- return Count;
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // User functions
- // Create a root node for the user, with mappings to all the path's in the
- // RootPaths string.
- BOOL CFsysThread::DoCreateUser(LPCSTR RootPaths)
- {
- CStringArray Roots;
- SMEM smUserRoot;
- CString Name, LinkPath;
- CString cBuf = RootPaths;
- LPSTR p = cBuf.GetBuffer(1);
- for(p = strtok(p, "rn"); p; p = strtok(NULL, "rn"))
- Roots.Add(p);
- if (Roots.GetUpperBound() < 0)
- {
- LogMsg(LOGF_WARNINGS,"User has no valid root path(s).");
- m_pFsys->m_FsysErrno = FSE_NO_ROOTPATH;
- return FALSE;
- }
- // Create the users root node
- if (!CreateDirNode(smUserRoot, "", NULL, NULL, NULL, NULL))
- {
- LogMsg(LOGF_WARNINGS,"Failed to create users root node");
- m_pFsys->m_FsysErrno = FSE_BAD_ROOTPATH;
- return FALSE;
- }
- // Create link nodes
- for(int i = 0; i <= Roots.GetUpperBound(); i++)
- {
- SMEM smDir;
- ParseRootpath(Roots[i], Name, LinkPath);
- CreateDirNode(smDir, Name, NULL, LinkPath, &smUserRoot, NULL);
- }
- *(SMEM *)&m_pFsys->m_FsysLparam = smUserRoot;
- if (!m_pFsys->m_Home.IsEmpty() && !ChDir(m_pFsys->m_Home))
- {
- LogMsg(LOGF_WARNINGS,"Failed to chdir to (users home) '%s'", m_pFsys->m_Home);
- goto cd_to_root;
- }
- else if (!ChDir("/")) // Fallbakc to root path
- {
- cd_to_root:
- LogMsg(LOGF_WARNINGS,"Failed to chdir to (users root) /");
- return FALSE;
- }
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- LogMsg(LOGF_DEBUG,"Created root node for the users file system.");
- return TRUE;
- }
- // Close a file.
- // No callback
- void CFsysThread::DoCloseFile(SMEM smNode)
- {
- pLock->WriteLock();
- FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
- pNode->f_OpenCnt--;
- if (pNode->f_Deleted)
- DeleteNode(smNode);
- else
- {
- if (pNode->f_Locked)
- {
- ASSERT(pNode->f_OpenCnt == 0);
- pNode->f_Locked = FALSE;
- ::ScanDir(pNode->Father, pNode->RealName ? pNode->RealName : pNode->Name, TRUE);
- }
- else if (pNode->f_CopyToHome)
- {
- ASSERT(FALSE); // Not yet implemented
- }
- }
- pLock->UnlockWrite();
- }
- // Create/Open a file
- BOOL CFsysThread::DoCreateFile(LPCSTR Path)
- {
- CString cMyPath = Path;
- SMEM smFileNode;
- DWORD Perms = 0;
- smFileNode = 0;
- if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_READ)
- Perms |= NODE_READ;
- if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
- Perms |= NODE_WRITE;
- if (!ParsePath(cMyPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- ScanPath(cMyPath, FALSE, FALSE, FALSE);
- pLock->WriteLock();
- if (!CheckPermissions(cMyPath, 0, Perms, &smFileNode))
- {
- pLock->UnlockWrite();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- // Handle unique file name
- #define MAX_CNT 20
- if (m_pFsys->m_CreateHdr.Flags & CWarFile::UNIQUE_NAME)
- {
- int Count = -1;
- SMEM smIgnore;
- for(Count = 0; Count < MAX_CNT; Count++)
- {
- CString cBuf;
- if (Count)
- cBuf.Format("%s(%d)", Path, Count);
- else
- cBuf = Path;
- if (!CheckPermissions(cBuf, 0, 0, &smIgnore) && CheckPermissions(cBuf, 0, NODE_WRITE, &smIgnore))
- {
- cMyPath = cBuf;
- smFileNode = smIgnore;
- break;
- }
- }
- if (Count == MAX_CNT)
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Can not create unique file name.", Path);
- return FALSE;
- }
- m_pFsys->m_CreateHdr.dwCreationDistribution &= ~(CREATE_ALWAYS | OPEN_EXISTING | OPEN_ALWAYS | TRUNCATE_EXISTING);
- m_pFsys->m_CreateHdr.dwCreationDistribution |= CREATE_NEW;
- }
- // Now, open the file...
- FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smFileNode);
- HANDLE hNewFileHandle = INVALID_HANDLE_VALUE;
- SMEM smParentDir;
- smParentDir = 0;
- SMEM smFsys;
- CString FsysPath;
- FILE_SYSTEM *pFsys = NULL;
- CDeviceDriver *pDev = NULL;
- if (pNode == NULL)
- {
- // New file.
- if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
- {
- // Get father node
- CString ParentPath = cMyPath;
- LPSTR p = ParentPath.GetBuffer(1);
- p = strrchr(p, '/');
- if (p)
- {
- *p++ = 0;
- ParentPath.ReleaseBuffer();
- if (!CheckPermissions(ParentPath, NODE_DIR, NODE_WRITE, &smParentDir))
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Not write access to parent dir.", Path);
- return FALSE;
- }
- // Permissions are OK. Now, get ready to create the node
- FsysPath = ResolveFsysPath(smParentDir, smFsys);
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
- if (!pFsys)
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - No file system on parent dir.", Path);
- return FALSE;
- }
- pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
- // Add the original file name to the path
- FsysPath += '/';
- FsysPath += p;
- }
- else
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Cant resolve parent dir.", Path);
- return FALSE;
- }
- }
- else
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - File don't exist.", Path);
- return FALSE;
- }
- }
- else
- {
- if (pNode->f_Locked || (pNode->f_OpenCnt && (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)))
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - File is open. Access denied.", Path);
- return FALSE;
- }
- FsysPath = ResolveFsysPath(smFileNode, smFsys);
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
- pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
- if (!pDev || FsysPath.IsEmpty() || !pNode)
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Unresolved internal references.", Path);
- return FALSE;
- }
- if (pNode->f_UseCopy)
- {
- ASSERT(FALSE); // Not yet implemented
- }
- }
- m_pFsys->m_CreateHdr.pFile->m_hFile = pDev->CreateFile(
- FsysPath,
- m_pFsys->m_CreateHdr.dwDesiredAccess,
- m_pFsys->m_CreateHdr.dwShareMode,
- m_pFsys->m_CreateHdr.lpSecurityAttributes,
- m_pFsys->m_CreateHdr.dwCreationDistribution,
- m_pFsys->m_CreateHdr.dwFlagsAndAttributes,
- m_pFsys->m_CreateHdr.hTemplateFile);
- if (m_pFsys->m_CreateHdr.pFile->m_hFile == INVALID_HANDLE_VALUE)
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Failed to open file.", cMyPath);
- return FALSE;
- }
- // File opened OK. See if this was a new file
- if (smParentDir)
- {
- DIR_NODE *pDir = NULL;
- pNode = NULL;
- ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
- if (FindNodeFromPath(smFileNode, cMyPath))
- {
- pNode = (FILE_NODE *)pSmem->__Ptr(smFileNode);
- if (pNode)
- {
- // The new node does not have any valid 'soft' permissions.
- // Give the user permission to create the file. We'll be a little
- // more restrictive as soon as the file is created :-)
- pNode->Perms &= ~NODE_SETTABLE;
- pNode->Perms |= 0666;
- }
- }
- if (!CheckPermissions(cMyPath, 0, NODE_WRITE, &smFileNode) || !smFileNode)
- {
- pDev->CloseHandle(m_pFsys->m_CreateHdr.pFile->m_hFile);
- m_pFsys->m_CreateHdr.pFile->m_hFile = INVALID_HANDLE_VALUE;
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Failed to create file.", FsysPath);
- // Delete the node
- if (pNode)
- {
- pNode->f_DeleteFile = TRUE; // Physically erase the file
- DeleteNode(smFileNode);
- }
- return FALSE;
- }
- if (pNode)
- {
- // Set permissions
- pDir = (DIR_NODE *)pSmem->__Ptr(pNode->Father);
- ASSERT(pDir != NULL);
- if (pDir && pDir->SpecialNewFilePerm)
- {
- pNode->Perms &= ~NODE_SETTABLE;
- pNode->Perms |= (pDir->SpecialNewFilePerm & NODE_SETTABLE);
- }
- pNode->Perms &= ~(m_pFsys->m_Umask & NODE_SETTABLE);
- if (m_pFsys->m_AssignTo != INVALID_USER_VALUE)
- pNode->User = m_pFsys->m_AssignTo;
- else
- pNode->User = m_pFsys->m_User;
- pNode->Class = m_pFsys->m_Class;
- if (pDir)
- {
- // Flush..
- pDir->f_Dirty = TRUE;
- Flush(pNode->Father);
- }
- }
- }
- ASSERT(pNode != NULL);
- if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
- {
- pNode->f_Locked = TRUE;
- }
- m_pFsys->m_CreateHdr.pFile->m_DEV = pDev;
- m_pFsys->m_CreateHdr.pFile->m_smNode = smFileNode;
- // Mark the file as open
- pNode->f_OpenCnt++;
- pLock->UnlockWrite();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- LogMsg(LOGF_DEBUG,"User opened file %s", FsysPath);
- return TRUE;
- }
- // Change the users working dir
- BOOL CFsysThread::DoChDirUser(LPCSTR Path)
- {
- if (!ChDir(Path))
- return FALSE;
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- LogMsg(LOGF_DEBUG,"User changed directory to %s", m_pFsys->m_CWD);
- return TRUE;
- }
- // Change the users working dir
- BOOL CFsysThread::ChDir(LPCSTR Path)
- {
- CString cMyPath = Path;
- SMEM smNode, smFsys;
- if (!ParsePath(cMyPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- ScanPath(cMyPath, FALSE, FALSE, FALSE);
- pLock->ReadLock();
- if (!CheckPermissions(cMyPath, NODE_DIR, NODE_EXEC, &smNode))
- {
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- m_pFsys->m_CWD = cMyPath;
- if (smNode)
- m_pFsys->m_DOSCWD = ResolveFsysPath(smNode, smFsys);
- else
- m_pFsys->m_DOSCWD = "**unresolved**";
- pLock->UnlockRead();
- return TRUE;
- }
- // Command line is parsed. Each token is seperated by ;
- // that is - normally "CMD;arg arg arg"
- BOOL CFsysThread::DoPrepereUserCmdLine(LPCSTR CmdLine)
- {
- CString cBuf;
- BOOL BreakAtSpace;
- m_pFsys->m_FsysPath2.Empty(); // Return buffer
- while(*CmdLine)
- {
- BreakAtSpace = (*CmdLine == '-');
- cBuf = "";
- while(*CmdLine)
- {
- if (BreakAtSpace && (*CmdLine == ' '))
- {
- while(*CmdLine == ' ')
- ++CmdLine;
- break;
- }
- if (*CmdLine == 'n')
- {
- while(*CmdLine == 'n')
- ++CmdLine;
- ++CmdLine;
- break;
- }
- cBuf += *CmdLine++;
- }
- if (!cBuf.IsEmpty())
- {
- if (!BreakAtSpace && (strpbrk(cBuf, "~{[*?")))
- {
- LogMsg(LOGF_WARNINGS,"DoPrepereUserCmdLine(%s) - Pattern matching is not yet implemented.", cBuf);
- }
- else
- {
- if (!m_pFsys->m_FsysPath2.IsEmpty())
- m_pFsys->m_FsysPath2 += 'n';
- m_pFsys->m_FsysPath2 += cBuf;
- }
- }
- }
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- // List. This is the full implementation of the UNIX ls command.
- // Create the temporary lists, sort it and write to a tmp file.
- // Return the tmp path to the file in user path 2.
- BOOL CFsysThread::DoList(LPCSTR ArgumentsUnparsed)
- {
- CVfSysLs ls;
- ls.m_pFsysThread = this;
- CCmdArgs UnixArgs;
- LPSTR p = m_pFsys->m_FsysPath1.GetBuffer(1);
- for(p = strtok(p, "n"); p; p = strtok(NULL,"n"))
- UnixArgs.AddArg(p);
- ls.Create(&UnixArgs, CLog::GetLog(), NULL, m_pFsys);
- if (ls.Exec() != 0)
- {
- m_pFsys->m_FsysErrno = FSE_UNIX_ERROR;
- LogMsg(LOGF_WARNINGS,"ls command failed.");
- return FALSE;
- }
- m_pFsys->m_FsysPath1.Empty();
- m_pFsys->m_FsysPath2 = ls.m_TmpName;
- fclose(ls.m_stdio);
- ls.m_stdio = NULL;
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- // Native War listing. Place output in
- // m_pFsys->m_FsysPath2
- BOOL CFsysThread::DoWlist(LPCSTR ArgumentsUnparsed)
- {
- ParsePath(m_pFsys->m_FsysPath1);
- ScanPath(m_pFsys->m_FsysPath1, FALSE, FALSE, FALSE);
- pLock->ReadLock();
- CFileList FileList;
- if (BldFileInfoList(FileList,m_pFsys->m_FsysPath1, TRUE))
- FileList.ListRaw(m_pFsys->m_FsysPath2);
- else
- {
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_UNIX_ERROR;
- FileList.Empty();
- return FALSE;
- }
- pLock->UnlockRead();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoChmod(CCmdArgs& Args)
- {
- CChmod Chmod(this);
- if (!Chmod.Create(&Args, CLog::GetLog(), BUFFER_STDIO, m_pFsys))
- return FALSE;
- Chmod.Exec();
- m_pFsys->m_Output = Chmod.m_stdout;
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- // Flush security information
- // Calling layer takes tare of locking...
- void CFsysThread::Flush(SMEM smDir)
- {
- DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- if (pDir && pDir->f_Dirty)
- {
- SMEM smFsys;
- CString FsysPath = ResolveFsysPath(smDir, smFsys);
- if (!FsysPath.IsEmpty())
- {
- HANDLE h = CFsysSecurity::OpenSecurityGroupForUpdate(FsysPath);
- if (h != INVALID_HANDLE_VALUE)
- {
- FILE_NODE *pNode;
- DIR_NODE *pThisDir;
- for(pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
- pNode;
- pNode = (FILE_NODE *)pSmem->__Ptr(pNode->Next))
- {
- if (pNode->f_Deleted)
- continue;
- if (pNode->Perms & NODE_DIR)
- pThisDir = (DIR_NODE *)pNode;
- else
- pThisDir = NULL;
- CFsysSecurity::FlushNode(h,
- pNode->Name,
- pNode->Perms & NODE_SETTABLE,
- pNode->User,
- pNode->Class,
- pNode->DlCount,
- pNode->Comment ? pNode->Comment : "",
- pThisDir ? pThisDir->SpecialNewFilePerm : 0);
- }
- CFsysSecurity::CloseSecurityGroup(h);
- pDir->f_Dirty = FALSE;
- }
- }
- }
- }
- BOOL CFsysThread::DoFsysStat()
- {
- pLock->ReadLock();
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)pSmem->m_Blks[0];
- if (!pSuper)
- return FALSE;
- CString cBuf;
- m_pFsys->m_Output = "VfSys shared memory statistics.n-------------------------------n";
- cBuf.Format("Segments: %d (size=%d) Nodes : %d Used nodes: %d Total memory: %d User memory %dn",
- pSuper->NumUsedSegments,
- pSuper->SegmentSize,
- pSuper->NumNodes,
- pSuper->UsedNodes,
- pSuper->PhysMemory,
- pSuper->UserMemory);
- m_pFsys->m_Output += cBuf;
- m_pFsys->m_Output += "nnVfSys statistics.n-----------------n";
- FILE_SYSTEM *pFsys = (FILE_SYSTEM *)pSmem->__Ptr(*(SMEM *)(&pSmem->m_Segments[0].m_pSMH->pUserPtr[USERPTR_FSYS]));
- while(pFsys)
- {
- cBuf.Format("File system '%s' (%s) FlushDelay=%d copy=%dn",
- pFsys->Vpath,
- pFsys->DOSPath,
- pFsys->FlushDelay,
- pFsys->DoCopy);
- m_pFsys->m_Output += cBuf;
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(pFsys->Next);
- }
- pLock->UnlockRead();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoCreateDirectory(LPCSTR Path)
- {
- CString cMyPath = Path, FsysPath;
- FILE_SYSTEM *pFsys = NULL;
- CDeviceDriver *pDev = NULL;
- if (!ParsePath(cMyPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- ScanPath(cMyPath, FALSE, FALSE, FALSE);
- pLock->ReadLock();
- if (!CheckPermissions(cMyPath, 0, NODE_WRITE, NULL))
- {
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- // Get the parent dir
- CString ParentDir = cMyPath;
- LPSTR p = ParentDir.GetBuffer(1);
- p = strrchr(p,'/');
- if (!p)
- {
- bad_path:
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- *p++ = 0;
- ParentDir.ReleaseBuffer();
- if (ParentDir.IsEmpty())
- ParentDir = "/";
- LPCSTR NewName = p;
- if (!*NewName)
- goto bad_path;
- // Get device driver
- SMEM smFsys, smDir;
- if (!FindNodeFromPath(smDir, ParentDir))
- {
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_PATH_NOT_FOUND;
- return FALSE;
- }
- FsysPath = ResolveFsysPath(smDir, smFsys);
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
- pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
- if (!pDev || FsysPath.IsEmpty())
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateDirectory(%s) - Unresolved internal references.", Path);
- return FALSE;
- }
- // Finally, create the directory
- if (FsysPath[FsysPath.GetLength()-1] != '/')
- FsysPath += '/';
- FsysPath += NewName;
- if (!pDev->CreateDirectory || !pDev->CreateDirectory(FsysPath))
- {
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateDirectory(%s) - Failed to create directory. (%s)",
- Path, FsysPath);
- return FALSE;
- }
- pLock->UnlockRead();
- LogMsg(LOGF_FILEACC,"Created directory '%s' (%s)", Path, FsysPath);
- ScanPath(cMyPath, FALSE, FALSE, TRUE);
- pLock->WriteLock();
- FILE_NODE *pNode;
- DIR_NODE *pDir;
- SMEM smNode;
- if (FindNodeFromPath(smNode, cMyPath))
- {
- pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
- if (pNode)
- {
- // Set permissions
- pNode->Perms |= 0777;
- pDir = (DIR_NODE *)pSmem->__Ptr(pNode->Father);
- ASSERT(pDir != NULL);
- if (pDir && pDir->SpecialNewFilePerm)
- {
- pNode->Perms &= ~NODE_SETTABLE;
- pNode->Perms |= (pDir->SpecialNewFilePerm & NODE_SETTABLE);
- }
- pNode->Perms &= ~(m_pFsys->m_Umask & NODE_SETTABLE);
- if (m_pFsys->m_AssignTo != INVALID_USER_VALUE)
- pNode->User = m_pFsys->m_AssignTo;
- else
- pNode->User = m_pFsys->m_User;
- pNode->Class = m_pFsys->m_Class;
- if (pDir)
- {
- // Flush..
- pDir->f_Dirty = TRUE;
- Flush(pNode->Father);
- }
- }
- }
- pLock->UnlockWrite();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoDeleteGeneric(LPCSTR Path, DWORD Flags)
- {
- CString cMyPath = Path, FsysPath;
- FILE_SYSTEM *pFsys = NULL;
- CDeviceDriver *pDev = NULL;
- CWarTimer Timer;
- if (!ParsePath(cMyPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- for(; !Timer.TimeOut(1000 * 120); Sleep(1000)) // Try for 2 minues (should be enough for IIS and other shit to close the file...)
- {
- pLock->WriteLock();
- ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
- if (!CheckPermissions(cMyPath, 0, NODE_WRITE, NULL))
- {
- perm_denied:
- pLock->UnlockWrite();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- // Get device driver
- SMEM smFsys, smDir;
- if (!FindNodeFromPath(smDir, cMyPath))
- {
- pLock->UnlockWrite();
- m_pFsys->m_FsysErrno = FSE_PATH_NOT_FOUND;
- return FALSE;
- }
- DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
- // Check type
- if (pDir->FileNode.Perms & NODE_DIR)
- {
- if (!(Flags & DELE_DIR))
- goto perm_denied;
- }
- else if (!(Flags & DELE_FILE))
- goto perm_denied;
- // Check if the file is in use...
- if (pDir->FileNode.f_OpenCnt || pDir->FileNode.f_Locked)
- goto perm_denied; // This can be handled better in the future :-)
- FsysPath = ResolveFsysPath(smDir, smFsys);
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
- pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
- if (!pDev || FsysPath.IsEmpty())
- {
- pLock->UnlockWrite();
- LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Unresolved internal references.", Path);
- return FALSE;
- }
- // Try to delete the file
- if ((pDir->FileNode.Perms & NODE_DIR) && !(pDir->FileNode.Perms & NODE_LINK))
- {
- // This is a bit tricky.. We have to look for .Index.txt and our own security file.
- // If they are the only files in the directory, delete them, and then delete the dir..
- CFileInfo Info;
- CString SearchPath = FsysPath;
- SearchPath += "/*";
- HANDLE h;
- if ((h = pDev->FindFirstFile(SearchPath, Info)) != INVALID_HANDLE_VALUE)
- {
- do
- {
- LPCSTR Name = Info.FileName();
- if (!stricmp(Name,".")
- || !stricmp(Name,"..")
- || !stricmp(Name,".Index.txt")
- || !stricmp(Name, SECFILE))
- continue;
- LogMsg(LOGF_DEBUG,"CFsysThread::DoDeleteGeneric(%s) - Directory is not empty.", Path);
- pDev->FindClose(h);
- pLock->UnlockWrite();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- } while(pDev->FindNextFile(h, Info));
- pDev->FindClose(h);
- }
- // Things looks all right... Clean up War files
- {
- CString Target;
- Target = FsysPath;
- Target += "/.Index.txt";
- pDev->DeleteFile(Target);
- Target = FsysPath;
- Target += '/';
- Target += SECFILE;
- pDev->DeleteFile(Target);
- }
- if (pDev->RemoveDirectory(FsysPath))
- {
- pLock->UnlockWrite();
- ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
- LogMsg(LOGF_FILEACC,"Deleted Directory '%s' (%s)", Path, FsysPath);
- break;
- }
- }
- else
- {
- if (pDev->DeleteFile(FsysPath))
- {
- pLock->UnlockWrite();
- ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
- LogMsg(LOGF_FILEACC,"Deleted file '%s' (%s)", Path, FsysPath);
- break;
- }
- }
- pLock->UnlockWrite();
- }
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoCreateLink(LPCSTR From, LPCSTR To)
- {
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoMoveFile(LPCSTR From, LPCSTR To)
- {
- CString FromPath = From, ToPath = To, FsysFromPath, FsysToPath;
- SMEM smFromNode, smToNode, smFromFsys, smToFsys, smToFatherDir;
- CDeviceDriver *pDev = NULL;
- FILE_SYSTEM *pFsys = NULL;
- DIR_NODE *pFatherDir;
- if (!ParsePath(FromPath) || !ParsePath(ToPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- pLock->WriteLock();
- // Check permissions
- ScanPath(FromPath, FALSE, FALSE, TRUE, FALSE);
- ScanPath(ToPath, FALSE, FALSE, TRUE, FALSE);
- if (!CheckPermissions(FromPath, 0, NODE_WRITE, NULL)
- || !CheckPermissions(ToPath, 0, NODE_WRITE, NULL))
- {
- perm_denied:
- pLock->UnlockWrite();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- // Get from node data
- if (!FindNodeFromPath(smFromNode, FromPath))
- goto perm_denied;
- DIR_NODE *pFromDir = (DIR_NODE *)pSmem->__Ptr(smFromNode);
- ASSERT(pFromDir != NULL);
- if (!pFromDir)
- goto perm_denied;
- // Don't mess with files that are in use...
- if (ScanForBusyFiles(smFromNode))
- goto perm_denied;
- FsysFromPath = ResolveFsysPath(smFromNode, smFromFsys);
- // Get to node data
- if (FindNodeFromPath(smToNode, ToPath))
- {
- DIR_NODE *pToDir = (DIR_NODE *)pSmem->__Ptr(smToNode);
- if ((pToDir->FileNode.Perms & NODE_DIR) == 0)
- goto perm_denied; // Not a directory
- ToPath += '/';
- LPCSTR p = strrchr(FromPath, '/');
- if (!p || !*++p || (*p == '/'))
- goto perm_denied; // Invalid path
- ToPath += p;
- }
- if (FindNodeFromPath(smToNode, ToPath))
- goto perm_denied; // File exist
- // Get the new path's father dir
- CString ToPathFather = ToPath;
- LPSTR p = ToPathFather.GetBuffer(1);
- p = strrchr(p,'/');
- if (p)
- {
- *p = 0;
- if (!*++p || (*p == '/'))
- goto perm_denied; // Invalid path
- }
- else
- goto perm_denied; // Invalid path
- ToPathFather.ReleaseBuffer();
- if (!FindNodeFromPath(smToFatherDir, ToPathFather))
- goto perm_denied; // No father...
- DIR_NODE *pToFatherDir = (DIR_NODE *)pSmem->__Ptr(smToFatherDir);
- if ((pToFatherDir->FileNode.Perms & NODE_DIR) == 0)
- goto perm_denied; // Not a directory
- FsysToPath = ResolveFsysPath(smToFatherDir, smToFsys);
- FsysToPath += '/';
- FsysToPath += p;
- // Use origin's file system
- pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFromFsys);
- pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
- // See if we can do a simple rename
- if (smToFatherDir == pFromDir->FileNode.Father)
- {
- CString NewName = p, OldName = pFromDir->FileNode.RealName;
- if (NewName.IsEmpty() || OldName.IsEmpty())
- goto perm_denied; // Illegal path
- if (!pDev->MoveFile(FsysFromPath, FsysToPath))
- goto perm_denied; // Permission denied
- ChangeNodeInformation(&pFromDir->FileNode, NewName, NewName, NULL, NULL);
- goto done;
- }
- // Move
- if (!pDev->MoveFile(FsysFromPath, FsysToPath))
- goto perm_denied; // Permission denied
- // Fix permissions
- // Don't use the file system. Relink the node to the new origin dir and
- // save it.
- UnlinkNode(smFromNode);
- LinkToFather(smFromNode, smToFatherDir);
- pFatherDir = (DIR_NODE *)pSmem->__Ptr(smToFatherDir);
- pFatherDir->f_Dirty = TRUE;
- Flush(smToFatherDir);
- done:
- pLock->UnlockWrite();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }
- BOOL CFsysThread::DoStat(LPCSTR Path)
- {
- CString cMyPath = Path;
- SMEM smNode;
- if (!ParsePath(cMyPath))
- {
- m_pFsys->m_FsysErrno = FSE_BAD_PATH;
- return FALSE;
- }
- ScanPath(cMyPath, FALSE, FALSE, FALSE);
- pLock->ReadLock();
- if (!CheckPermissions(cMyPath, 0, NODE_READ, &smNode))
- {
- perm_denied:
- pLock->UnlockRead();
- m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
- return FALSE;
- }
- FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
- if (!pNode)
- {
- ASSERT(FALSE);
- goto perm_denied;
- }
- m_pFsys->m_FileLen = pNode->Size;
- m_pFsys->m_FileTime = pNode->LastWriteDate;
- m_pFsys->m_FilePerms = pNode->Perms;
- pLock->UnlockRead();
- ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
- return TRUE;
- }