VirtualFileSystem.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:43k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // VirtualFileSystem.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. // For now, we don't support non-daemon programs
  5. //#include "WarSoftware.h"
  6. #include "WarDaemon.h"
  7. #include "WarFsys.h"
  8. #include "VfFSys.h"
  9. #include "UnixFsysTypes.h"
  10. #include "FsysSecurity.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CVirtualFileSystem
  18. CLinkedList CVirtualFileSystem::m_FreeThreads;
  19. CLinkedList CVirtualFileSystem::m_BusyThreads;
  20. CVirtualFileSystem::CVirtualFileSystem()
  21. {
  22. }
  23. CVirtualFileSystem::~CVirtualFileSystem()
  24. {
  25. }
  26. void CVirtualFileSystem::Shutdown()
  27. {
  28. // Clean up. Only one object pr. process, so we can do it right :-)
  29. CLinkedList MyList;
  30. CWinThread *pThread;
  31. MyList = m_FreeThreads;
  32. MyList += m_BusyThreads;
  33. while(pThread = (CWinThread *) MyList.GetAndDeleteFirst())
  34. {
  35. pThread->AssertValid();
  36. if (!::PostThreadMessage(pThread->m_nThreadID, FSM_QUIT, 0, 0))
  37. {
  38. CLog::GetLog()->LogMsg(LOGF_ERROR,"CVirtualFileSystem::Shutdown() - PostThreadMessage failed: %s", 
  39. GetLastErrorText());
  40. // Patch. Just kill the linked lists..
  41. while(m_FreeThreads.GetAndDeleteFirst());
  42. while(m_BusyThreads.GetAndDeleteFirst());
  43. }
  44. }
  45. while(m_FreeThreads.GetItemCount() || m_BusyThreads.GetItemCount())
  46. Sleep(100);
  47. }
  48. BEGIN_MESSAGE_MAP(CVirtualFileSystem, CWnd)
  49. //{{AFX_MSG_MAP(CVirtualFileSystem)
  50. // NOTE - the ClassWizard will add and remove mapping macros here.
  51. //}}AFX_MSG_MAP
  52. ON_MESSAGE(FSM_CALLBACK, mhCallback)
  53. ON_MESSAGE(FSM_CREATEFILE, mhCreateFile)
  54. ON_MESSAGE(FSM_CREATEUSER, mhCreate)
  55. ON_MESSAGE(FSM_CHDIR, mhChdir)
  56. ON_MESSAGE(FSM_CHMOD, mhChmod)
  57. ON_MESSAGE(FSM_PRPCMDLINE, mhPreperePath)
  58. ON_MESSAGE(FSM_LIST, mhList)
  59. ON_MESSAGE(FSM_WLST, mhWlist)
  60. ON_MESSAGE(FSM_CLOSEFILE, mhCloseFile)
  61. ON_MESSAGE(FSM_FSYSSTAT, mhFsysstat)
  62. ON_MESSAGE(FSM_CREATEDIR, mhCreateDir)
  63. ON_MESSAGE(FSM_DELEDIR, mhDeleteDir)
  64. ON_MESSAGE(FSM_DELEFILE, mhDeleteFile)
  65. ON_MESSAGE(FSM_DELE, mhDeleteGeneric)
  66. ON_MESSAGE(FSM_LINK, mhLinkFile)
  67. ON_MESSAGE(FSM_MOVE, mhMoveFile)
  68. ON_MESSAGE(FSM_QUIT, mhQuit)
  69. ON_MESSAGE(FSM_STAT, mhStat)
  70. END_MESSAGE_MAP()
  71. // Get a free worker thread. Then, mark it as busy.
  72. // If pTherad is <> NULL, release the thread
  73. CWinThread *CVirtualFileSystem::GetThread(CWinThread *pTherad, HWND hWnd)
  74. {
  75. static CCriticalSection Lock;
  76. Lock.Lock();
  77. if (pTherad == NULL)
  78. {
  79. if ((pTherad = (CWinThread *)m_FreeThreads.GetAndDeleteFirst()) == NULL)
  80. {
  81. CFsysThread *pThreadObj = new CFsysThread;
  82. pThreadObj->m_CallbackWin = hWnd;
  83. if ((pTherad = AfxBeginThread(CFsysThread::EntryPoint, (LPVOID)pThreadObj)) == NULL)
  84. delete pThreadObj;
  85. else
  86. {
  87. pThreadObj->m_Lock.Lock();
  88. pThreadObj->m_Lock.Unlock();
  89. }
  90. }
  91. if (pTherad)
  92. {
  93. // Wait for the thread to initialize
  94. m_FreeThreads.DeletePtr((LPVOID)pTherad);
  95. m_BusyThreads.AddLast((LPVOID)pTherad);
  96. }
  97. }
  98. else
  99. {
  100. m_BusyThreads.DeletePtr(pTherad);
  101. m_FreeThreads.AddLast((LPVOID)pTherad);
  102. }
  103. Lock.Unlock();
  104. return pTherad;
  105. }
  106. // Call a worker thread and pass the request on
  107. LONG CVirtualFileSystem::ProcessRequest(int Type, WPARAM wParam, LPARAM lParam)
  108. {
  109. CWinThread *pThrd = GetThread(NULL,m_hWnd);
  110. if (!pThrd)
  111. return FALSE;
  112. ::PostThreadMessage(pThrd->m_nThreadID, Type, wParam, lParam);
  113. return TRUE;
  114. }
  115. /////////////////////////////////////////////////////////////////////////////
  116. // CVirtualFileSystem message handlers
  117. LONG CVirtualFileSystem::mhCallback( WPARAM wParam, LPARAM lParam)
  118. {
  119. CUserFsys *pFsys = (CUserFsys *)wParam;
  120. pFsys->OnCallback(lParam);
  121. return 0;
  122. }
  123. LONG CVirtualFileSystem::mhCreateFile( WPARAM wParam, LPARAM lParam)
  124. {
  125. CString Roots = (LPCSTR)lParam;
  126. return ProcessRequest(FSM_CREATEFILE, wParam, (LPARAM)(LPCSTR)Roots);
  127. }
  128. LONG CVirtualFileSystem::mhCreate( WPARAM wParam, LPARAM lParam)
  129. {
  130. CString Roots = (LPCSTR)lParam;
  131. return ProcessRequest(FSM_CREATEUSER, wParam, (LPARAM)(LPCSTR)Roots);
  132. }
  133. LONG CVirtualFileSystem::mhChdir( WPARAM wParam, LPARAM lParam)
  134. {
  135. CString Roots = (LPCSTR)lParam;
  136. return ProcessRequest(FSM_CHDIR, wParam, (LPARAM)(LPCSTR)Roots);
  137. }
  138. LONG CVirtualFileSystem::mhChmod( WPARAM wParam, LPARAM lParam)
  139. {
  140. return ProcessRequest(FSM_CHMOD, wParam, NULL);
  141. }
  142. LONG CVirtualFileSystem::mhPreperePath( WPARAM wParam, LPARAM lParam)
  143. {
  144. CString Roots = (LPCSTR)lParam;
  145. return ProcessRequest(FSM_PRPCMDLINE, wParam, (LPARAM)(LPCSTR)Roots);
  146. }
  147. LONG CVirtualFileSystem::mhList( WPARAM wParam, LPARAM lParam)
  148. {
  149. CString Roots = (LPCSTR)lParam;
  150. return ProcessRequest(FSM_LIST, wParam, (LPARAM)(LPCSTR)Roots);
  151. }
  152. LONG CVirtualFileSystem::mhWlist( WPARAM wParam, LPARAM lParam)
  153. {
  154. CString Path = (LPCSTR)lParam;
  155. return ProcessRequest(FSM_WLST, wParam, (LPARAM)(LPCSTR)Path);
  156. }
  157. LONG CVirtualFileSystem::mhCloseFile( WPARAM wParam, LPARAM lParam)
  158. {
  159. return ProcessRequest(FSM_CLOSEFILE, wParam, lParam);
  160. }
  161. LONG CVirtualFileSystem::mhFsysstat( WPARAM wParam, LPARAM lParam)
  162. {
  163. return ProcessRequest(FSM_FSYSSTAT, wParam, lParam);
  164. }
  165. LONG CVirtualFileSystem::mhCreateDir( WPARAM wParam, LPARAM lParam)
  166. {
  167. return ProcessRequest(FSM_CREATEDIR, wParam, lParam);
  168. }
  169. LONG CVirtualFileSystem::mhDeleteDir( WPARAM wParam, LPARAM lParam)
  170. {
  171. return ProcessRequest(FSM_DELEDIR, wParam, lParam);
  172. }
  173. LONG CVirtualFileSystem::mhDeleteFile( WPARAM wParam, LPARAM lParam)
  174. {
  175. return ProcessRequest(FSM_DELEFILE, wParam, lParam);
  176. }
  177. LONG CVirtualFileSystem::mhDeleteGeneric( WPARAM wParam, LPARAM lParam)
  178. {
  179. return ProcessRequest(FSM_DELE, wParam, lParam);
  180. }
  181. LONG CVirtualFileSystem::mhLinkFile( WPARAM wParam, LPARAM lParam)
  182. {
  183. return ProcessRequest(FSM_LINK, wParam, lParam);
  184. }
  185. LONG CVirtualFileSystem::mhMoveFile( WPARAM wParam, LPARAM lParam)
  186. {
  187. return ProcessRequest(FSM_MOVE, wParam, lParam);
  188. }
  189. LONG CVirtualFileSystem::mhQuit( WPARAM wParam, LPARAM lParam)
  190. {
  191. Shutdown();
  192. return TRUE;
  193. }
  194. LONG CVirtualFileSystem::mhStat( WPARAM wParam, LPARAM lParam)
  195. {
  196. return ProcessRequest(FSM_STAT, wParam, lParam);
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // CFsysThread
  200. int CFsysThread::m_NumThreadsStarted = 0;
  201. CFsysThread::CFsysThread()
  202. {
  203. m_Lock.Lock();
  204. m_SeqNo = 0;
  205. m_CallbackWin = NULL;
  206. }
  207. CFsysThread::~CFsysThread()
  208. {
  209. }
  210. void CFsysThread::LogMsg(int flag, LPCSTR Format, ...)
  211. {
  212. if (!ShouldLog(CLog::GetLog(), flag))
  213. return;
  214. {
  215. CString cBuf;
  216. ASSERT(AfxIsValidString(Format, FALSE));
  217. cBuf.Format("VfSys::%s: %s", m_pFsys->m_Name, Format);
  218. va_list argList;
  219. va_start(argList, Format);
  220. CLog::GetLog()->LogMsgV(flag, cBuf, argList);
  221. va_end(argList);
  222. }
  223. }
  224. UINT CFsysThread::EntryPoint(LPVOID pParam)
  225. {
  226. CFsysThread *pMe = (CFsysThread *)pParam;
  227. return pMe->Process();
  228. }
  229. UINT CFsysThread::Process()
  230. {
  231. // Set up a message queue
  232. MSG msg;
  233. PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);
  234. BOOL Rval;
  235. m_SeqNo = ++m_NumThreadsStarted;
  236. // Signal that we are ready
  237. m_Lock.Unlock();
  238. // Go into message loop
  239. CLog::GetLog()->LogMsg(LOGF_DEBUG,"CFsysThread::Process() Thread #%d (0x%08x) starting up.", m_SeqNo, AfxGetThread());
  240. while(GetMessage(&msg,NULL,0,0) == TRUE)
  241. {
  242. CUserFsys *pFsys = (CUserFsys *)msg.wParam;
  243. if (pFsys)
  244. {
  245. pFsys->m_FsysErrno = 0;
  246. pFsys->m_DOSErrno = 0;
  247. m_pFsys = pFsys;
  248. }
  249. switch(msg.message)
  250. {
  251. case FSM_QUIT:
  252. case WM_QUIT:
  253. goto done;
  254. case FSM_CREATEFILE:
  255. Rval = DoCreateFile(pFsys->m_FsysPath1);
  256. break;
  257. case FSM_CREATEUSER:
  258. Rval = DoCreateUser(pFsys->m_FsysPath1);
  259. break;
  260. case FSM_CHDIR:
  261. Rval = DoChDirUser(pFsys->m_FsysPath1);
  262. break;
  263. case FSM_CHMOD:
  264. Rval = DoChmod(pFsys->m_Args);
  265. break;
  266. case FSM_PRPCMDLINE:
  267. Rval = DoPrepereUserCmdLine(pFsys->m_FsysPath1);
  268. break;
  269. case FSM_LIST:
  270. Rval = DoList(pFsys->m_FsysPath1);
  271. break;
  272. case FSM_CLOSEFILE:
  273. Rval = TRUE;
  274. DoCloseFile(*(SMEM *)&msg.lParam);
  275. break;
  276. case FSM_WLST:
  277. Rval = DoWlist(pFsys->m_FsysPath1);
  278. break;
  279. case FSM_FSYSSTAT:
  280. Rval = DoFsysStat();
  281. break;
  282. case FSM_CREATEDIR:
  283. Rval = DoCreateDirectory(pFsys->m_FsysPath1);
  284. break;
  285. case FSM_DELEDIR:
  286. Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_DIR);
  287. break;
  288. case FSM_DELEFILE:
  289. Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_FILE);
  290. break;
  291. case FSM_DELE:
  292. Rval = DoDeleteGeneric(pFsys->m_FsysPath1, DELE_DIR | DELE_FILE);
  293. break;
  294. case FSM_LINK:
  295. Rval = DoCreateLink(pFsys->m_FsysPath1, pFsys->m_FsysPath2);
  296. break;
  297. case FSM_MOVE:
  298. Rval = DoMoveFile(pFsys->m_FsysPath1, pFsys->m_FsysPath2);
  299. break;
  300. case FSM_STAT:
  301. Rval = DoStat(pFsys->m_FsysPath1);
  302. break;
  303. default:
  304. CLog::GetLog()->LogMsg(LOGF_WARNINGS,"CFsysThread::Process() - Got unknown message %u", msg.message);
  305. pFsys->m_FsysErrno = FSE_UNKNOWN_CALL;
  306. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)pFsys, 0);
  307. }
  308. if (!Rval)
  309. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)msg.wParam, 0);
  310. // Release the thread
  311. CVirtualFileSystem::GetThread(AfxGetThread(), NULL);
  312. }
  313. done:
  314. CLog::GetLog()->LogMsg(LOGF_DEBUG,"CFsysThread::Process() Thread #%d shutting down.", m_SeqNo);
  315. CVirtualFileSystem::m_FreeThreads.DeletePtr((LPVOID)AfxGetThread());
  316. delete this;
  317. return 0;
  318. }
  319. BOOL CFsysThread::ParseRootpath(LPCSTR RootPath, CString& Name, CString& LinkPath)
  320. {
  321. CString cBuf = RootPath;
  322. LPSTR p = cBuf.GetBuffer(1);
  323. p = strchr(p, ',');
  324. if (p)
  325. *p++ = 0;
  326. cBuf.ReleaseBuffer();
  327. LinkPath = cBuf;
  328. Name = p ? p : "";
  329. return TRUE;
  330. }
  331. // Scan a path, starting at the user root...
  332. BOOL CFsysThread::ScanPath(LPCSTR Path, BOOL FullScanToPath, BOOL Recursive, BOOL Force, BOOL DoLock)
  333. {
  334. if (DoLock)
  335. pLock->WriteLock();
  336. DIR_NODE *pRoot = GetRootNode();
  337. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(pRoot->Son);
  338. while(pDir)
  339. {
  340. if (pDir->FileNode.LinkTo)
  341. {
  342. CString ParsedPath = Path;
  343. ParsePath(ParsedPath);
  344. CString MyPath = pDir->FileNode.LinkTo;
  345. if (!MyPath.IsEmpty() && (MyPath[MyPath.GetLength() -1] == '/'))
  346. MyPath.ReleaseBuffer(MyPath.GetLength() -1);
  347. MyPath += ParsedPath;
  348. ::ScanPath(MyPath, FullScanToPath, Recursive, Force);
  349. }
  350. pDir = (DIR_NODE *)pSmem->__Ptr(pRoot->FileNode.Next);
  351. }
  352. if (DoLock)
  353. pLock->UnlockWrite();
  354. return TRUE;
  355. }
  356. DIR_NODE *CFsysThread::GetRootNode()
  357. {
  358. SMEM *pSM = (SMEM *)&m_pFsys->m_FsysLparam;
  359. DIR_NODE *pRoot = (DIR_NODE *)pSmem->__Ptr(*pSM);
  360. return pRoot;
  361. }
  362. BOOL CFsysThread::ParsePath(CString& OrigPath)
  363. {
  364. CString MyPath = OrigPath;
  365. int cnt = 0;
  366. LPCSTR Path = OrigPath;
  367. if (*Path != '/')
  368. {
  369. // Path is relative to 
  370. CString cBuf = m_pFsys->m_CWD;
  371. if (cBuf.GetLength() && (cBuf[cBuf.GetLength() -1] != '/'))
  372. cBuf += '/';
  373. cBuf += Path;
  374. MyPath = OrigPath = cBuf;
  375. Path = OrigPath;
  376. }
  377. char *Buf = MyPath.GetBuffer(1);
  378. while(*Path)
  379. {
  380. if (*Path == '/')
  381. {
  382. // /C/.. /C/./any  /C/any/. /C/any/../.any /C/any..
  383. if (Path[1] == '.')
  384. {
  385. if (!Path[2] || (Path[2] == '/'))
  386. {
  387. // /C/any/. style. Just ignore
  388. Path += 2;
  389. continue;
  390. }
  391. if (Path[2] == '.')
  392. {
  393. if (!Path[3] || (Path[3] == '/'))
  394. {
  395. // /C/any/.. /C/any/../test style. Move back one 
  396. if (cnt == 0)
  397. {
  398. LogMsg(LOGF_DEBUG,"RealPath(%s) - invalid ../ ", OrigPath);
  399. return FALSE;
  400. }
  401. while(--cnt && (Buf[cnt] != '/'))
  402. {
  403. ASSERT(cnt >= 0);
  404. }
  405. Path += 3;
  406. continue;
  407. }
  408. }
  409. }
  410. }
  411. // Default
  412. Buf[cnt++] = *Path++;
  413. }
  414. if (cnt == 0)
  415. OrigPath = "/"; // Never move beoind /
  416. else
  417. {
  418. Buf[cnt] = 0;
  419. OrigPath = Buf;
  420. }
  421. return TRUE;
  422. }
  423. BOOL CFsysThread::UserHasPermission(DWORD Perms, DWORD PermWanted)
  424. {
  425. if (PermWanted & NODE_EXEC)
  426. {
  427. if (!(Perms & (NODE_OEXEC | NODE_GEXEC | NODE_AEXEC)))
  428. return FALSE; // No permissions
  429. }
  430. if (PermWanted & NODE_READ)
  431. {
  432. if (!(Perms & (NODE_OREAD | NODE_GREAD | NODE_AREAD)))
  433. return FALSE; // No permissions
  434. }
  435. if (PermWanted & NODE_WRITE)
  436. {
  437. if (!(Perms & (NODE_0WRITE | NODE_GWRITE | NODE_AWRITE)))
  438. return FALSE; // No permissions
  439. }
  440. if (PermWanted & NODE_HIDE)
  441. {
  442. if (!(Perms & (NODE_OHIDE | NODE_GHIDE | NODE_AHIDE)))
  443. return FALSE; // No permissions
  444. }
  445. if (PermWanted & NODE_FREE)
  446. {
  447. if (!(Perms & (NODE_OFREE | NODE_GFREE | NODE_AFREE)))
  448. return FALSE; // No permissions
  449. }
  450. return TRUE;
  451. }
  452. // Check if a user has a desired permission to a node
  453. // Note: pDir can be any node type
  454. BOOL CFsysThread::UserHasPermission(DIR_NODE *pDir, DWORD Perm)
  455. {
  456. if (m_pFsys->m_IsAdmin || m_pFsys->m_IsSystem)
  457. return TRUE;
  458. if (pDir->FileNode.LinkTo)
  459. {
  460. SMEM smDir;
  461. FindNodeFromPath(smDir, pDir->FileNode.LinkTo); 
  462. DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
  463. if (pLinkTo)
  464. return UserHasPermission(pLinkTo, Perm);
  465. LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
  466. return FALSE; 
  467. }
  468. int Mask = S_IRWXO;
  469. int Perms = pDir->FileNode.Perms;
  470. if (pDir->FileNode.User == m_pFsys->m_User)
  471. Mask |= S_IRWXU;
  472. if (pDir->FileNode.Class == m_pFsys->m_Class)
  473. Mask |= S_IRWXG;
  474. BOOL HasAccess = UserHasPermission(Perms & Mask, Perm);
  475. if (!HasAccess)
  476. {
  477. // Check for additional permissions
  478. USER *pUsers = (USER *)pSmem->__Ptr(pDir->FileNode.MoreUsers);
  479. if (pUsers)
  480. {
  481. Mask |= S_IRWXG;
  482. for(int i = 0; pUsers[i] != INVALID_USER_VALUE; i++)
  483. {
  484. if ((pUsers[i] == m_pFsys->m_User) || (pUsers[i] == m_pFsys->m_Class))
  485. {
  486. HasAccess = UserHasPermission(Perms & Mask, Perm);
  487. break;
  488. }
  489. }
  490. }
  491. }
  492. return HasAccess;
  493. }
  494. // Check if the user has permission to a path.
  495. // If psmNode != NULL, return the destination node on success
  496. BOOL CFsysThread::CheckPermissions(LPCSTR Path, DWORD ReqType, DWORD Perm, SMEM *psmNode)
  497. {
  498. DIR_NODE *pRoot = GetRootNode();
  499. SMEM smDir = pRoot->Son;
  500. CPathArray PathArray;
  501. PathArray.ParsePathToArray(Path);
  502. BOOL PermissionToCreate = FALSE;
  503. DIR_NODE *pDir = NULL;
  504. for(int Index = 0; Index <= PathArray.GetUpperBound(); Index++)
  505. {
  506. smDir = Index ? FindNode(smDir, PathArray[Index]) : pRoot->Son;
  507. if (!smDir)
  508. {
  509. if (psmNode)
  510. {
  511. psmNode = 0;
  512. }
  513. return PermissionToCreate;
  514. }
  515. pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  516. if (pDir->FileNode.Perms & NODE_LINK)
  517. {
  518. // Follow link
  519. if (!FindNodeFromPath(smDir, pDir->FileNode.LinkTo))
  520. {
  521. LogMsg(LOGF_WARNINGS,"CFsysThread::CheckPermissions() - Unresolved soft link: '%s'", pDir->FileNode.LinkTo);
  522. return FALSE;
  523. }
  524. pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  525. }
  526. if (pDir->FileNode.Perms & NODE_DIR)
  527. {
  528. // Check execute permission
  529. if (!UserHasPermission(pDir, NODE_EXEC))
  530. return FALSE;
  531. }
  532. if (Index == (PathArray.GetUpperBound() - 1))
  533. {
  534. // Special case. If the user want to create something, check the
  535. // permissions on this level.
  536. if ((Perm & NODE_WRITE) && (pDir->FileNode.Perms & NODE_DIR))
  537. {
  538. PermissionToCreate = UserHasPermission(pDir, NODE_EXEC | NODE_WRITE);
  539. }
  540. }
  541. }
  542. ASSERT(pDir != NULL);
  543. if (ReqType && !(pDir->FileNode.Perms & ReqType))
  544. return FALSE;
  545. if (!UserHasPermission(pDir, Perm))
  546. return FALSE;
  547. if (psmNode)
  548. *psmNode = smDir;
  549. return TRUE;
  550. }
  551. // Look for the name in the directory, and in
  552. // hard linked subdirs
  553. SMEM CFsysThread::FindNode(SMEM& smDir, LPCSTR Name)
  554. {
  555. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  556. SMEM Rval;
  557. Rval = 0;
  558. if (!pDir)
  559. return Rval;
  560. while(!pDir->FileNode.Name && pDir->FileNode.LinkTo)
  561. {
  562. SMEM smLinkDir;
  563. FindNodeFromPath(smLinkDir, pDir->FileNode.LinkTo); 
  564. DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smLinkDir);
  565. if (pLinkTo)
  566. {
  567. pDir = pLinkTo;
  568. }
  569. else
  570. {
  571. LogMsg(LOGF_WARNINGS, 
  572. "CFsysThread::FindNode(%s) - Broken link detected in file system (%s).", 
  573. Name, pDir->FileNode.LinkTo);
  574. return Rval;
  575. }
  576. }
  577. FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
  578. Rval = pDir->Son;
  579. while(pNode)
  580. {
  581. if (!pNode->Name && pNode->LinkTo)
  582. {
  583. SMEM smLinkDir;
  584. FindNodeFromPath(smLinkDir, pNode->LinkTo); 
  585. DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
  586. if (pLinkTo)
  587. {
  588. SMEM smTest = FindNode(smLinkDir, Name);
  589. if (smTest)
  590. return smTest;
  591. }
  592. else
  593. {
  594. LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
  595. }
  596. }
  597. else if (pNode->Name && !stricmp(pNode->Name, Name))
  598. break;
  599. Rval = pNode->Next;
  600. pNode = (FILE_NODE *)pSmem->__Ptr(Rval);
  601. }
  602. return Rval;
  603. }
  604. ///////////////////////////////////////////////////////////////////////////
  605. // Build a CFileInfoList
  606. BOOL CFsysThread::BldFileInfoList(CFileList& FileList, LPCSTR Path, BOOL ListDir)
  607. {
  608. CString MyPath = Path;
  609. ParsePath(MyPath);
  610. CString Pattern = "*", COrigPath = MyPath;
  611. LPSTR pp = strrchr(MyPath.GetBuffer(1), '/'), p = pp;
  612. LogMsg(LOGF_DEBUG,"BldFileInfoList() INFO: Path = '%s' and %s", Path, ListDir ? "DIR" : "FILE");
  613. if (ListDir)
  614. {
  615. if (p && !strpbrk(p, "*?"))
  616. {
  617. if (AddFileInfoListPath(FileList, MyPath, Pattern))
  618. return TRUE;
  619. }
  620. }
  621. if (p && (p >= pp))
  622. {
  623. *p++ = 0;
  624. Pattern = p;
  625. }
  626. else
  627. {
  628. LogMsg(LOGF_DEBUG,"BldFileInfoList() - Cannot list '%s'.", Path);
  629. return FALSE;
  630. }
  631. AddFileInfoListPath(FileList, MyPath, Pattern);
  632. return TRUE;
  633. }
  634. int CFsysThread::AddFileInfoListPath(CFileList& FileList, LPCSTR Path, LPCSTR Pattern)
  635. {
  636. SMEM smNode;
  637. // Get the dir to list
  638. if (!CheckPermissions(Path, NODE_DIR, NODE_READ, &smNode))
  639. {
  640. LogMsg(LOGF_DEBUG,"AddFileInfoListPath() - Permission denied on '%s'.", Path);
  641. return FALSE;
  642. }
  643. return AddFileInfoListPath(FileList, smNode, Pattern);
  644. }
  645. int CFsysThread::AddFileInfoListPath(CFileList& FileList, SMEM smDir, LPCSTR Pattern)
  646. {
  647. int Count = 0;
  648. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  649. SMEM Rval;
  650. Rval = 0;
  651. if (!pDir)
  652. return Count;
  653. while(!pDir->FileNode.Name && pDir->FileNode.LinkTo)
  654. {
  655. SMEM smLinkDir;
  656. FindNodeFromPath(smLinkDir, pDir->FileNode.LinkTo); 
  657. DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smLinkDir);
  658. if (pLinkTo)
  659. {
  660. pDir = pLinkTo;
  661. }
  662. }
  663. FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
  664. if (!pNode)
  665. LogMsg(LOGF_DEBUG,"AddFileInfoListPath() - pNode is NULL. Nothing to list...");
  666. while(pNode)
  667. {
  668. if (!pNode->Name && pNode->LinkTo)
  669. {
  670. SMEM smLinkDir;
  671. FindNodeFromPath(smLinkDir, pNode->LinkTo); 
  672. DIR_NODE *pLinkTo = (DIR_NODE *)pSmem->__Ptr(smDir);
  673. if (pLinkTo)
  674. {
  675. Count += AddFileInfoListPath(FileList, smLinkDir, Pattern);
  676. }
  677. else
  678. {
  679. LogMsg(LOGF_WARNINGS,"Link '%s' is unresolved", pDir->FileNode.LinkTo);
  680. }
  681. }
  682. else if (pNode->Name 
  683. && PatternMatchesName(pNode->Name, Pattern) 
  684. && (m_pFsys->m_IsAdmin || !UserHasPermission(pNode->Perms, NODE_HIDE)))
  685. {
  686. ++Count;
  687. FileList.Add(pNode);
  688. }
  689. Rval = pNode->Next;
  690. pNode = (FILE_NODE *)pSmem->__Ptr(Rval);
  691. }
  692. return Count;
  693. }
  694. ////////////////////////////////////////////////////////////////////////////////////////
  695. // User functions
  696. // Create a root node for the user, with mappings to all the path's in the 
  697. // RootPaths string. 
  698. BOOL CFsysThread::DoCreateUser(LPCSTR RootPaths)
  699. {
  700. CStringArray Roots;
  701. SMEM smUserRoot;
  702. CString Name, LinkPath;
  703. CString cBuf = RootPaths;
  704. LPSTR p = cBuf.GetBuffer(1);
  705. for(p = strtok(p, "rn"); p;  p = strtok(NULL, "rn"))
  706. Roots.Add(p);
  707. if (Roots.GetUpperBound() < 0)
  708. {
  709. LogMsg(LOGF_WARNINGS,"User has no valid root path(s).");
  710. m_pFsys->m_FsysErrno = FSE_NO_ROOTPATH;
  711. return FALSE;
  712. }
  713. // Create the users root node
  714. if (!CreateDirNode(smUserRoot, "", NULL, NULL, NULL, NULL))
  715. {
  716. LogMsg(LOGF_WARNINGS,"Failed to create users root node");
  717. m_pFsys->m_FsysErrno = FSE_BAD_ROOTPATH;
  718. return FALSE;
  719. }
  720. // Create link nodes
  721. for(int i = 0; i <= Roots.GetUpperBound(); i++)
  722. {
  723. SMEM smDir;
  724. ParseRootpath(Roots[i], Name, LinkPath);
  725. CreateDirNode(smDir, Name, NULL, LinkPath, &smUserRoot, NULL);
  726. }
  727. *(SMEM *)&m_pFsys->m_FsysLparam = smUserRoot;
  728. if (!m_pFsys->m_Home.IsEmpty() && !ChDir(m_pFsys->m_Home))
  729. {
  730. LogMsg(LOGF_WARNINGS,"Failed to chdir to (users home) '%s'", m_pFsys->m_Home);
  731. goto cd_to_root;
  732. }
  733. else if (!ChDir("/")) // Fallbakc to root path
  734. {
  735. cd_to_root:
  736. LogMsg(LOGF_WARNINGS,"Failed to chdir to (users root) /");
  737. return FALSE;
  738. }
  739. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  740. LogMsg(LOGF_DEBUG,"Created root node for the users file system.");
  741. return TRUE;
  742. }
  743. // Close a file.
  744. // No callback
  745. void CFsysThread::DoCloseFile(SMEM smNode)
  746. {
  747. pLock->WriteLock();
  748. FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
  749. pNode->f_OpenCnt--;
  750. if (pNode->f_Deleted)
  751. DeleteNode(smNode);
  752. else
  753. {
  754. if (pNode->f_Locked)
  755. {
  756. ASSERT(pNode->f_OpenCnt == 0);
  757. pNode->f_Locked = FALSE;
  758. ::ScanDir(pNode->Father, pNode->RealName ? pNode->RealName : pNode->Name, TRUE);
  759. }
  760. else if (pNode->f_CopyToHome)
  761. {
  762. ASSERT(FALSE); // Not yet implemented
  763. }
  764. }
  765. pLock->UnlockWrite();
  766. }
  767. // Create/Open a file
  768. BOOL CFsysThread::DoCreateFile(LPCSTR Path)
  769. {
  770. CString cMyPath = Path;
  771. SMEM smFileNode;
  772. DWORD Perms = 0;
  773. smFileNode = 0;
  774. if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_READ)
  775. Perms |= NODE_READ;
  776. if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
  777. Perms |= NODE_WRITE;
  778. if (!ParsePath(cMyPath))
  779. {
  780. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  781. return FALSE;
  782. }
  783. ScanPath(cMyPath, FALSE, FALSE, FALSE);
  784. pLock->WriteLock();
  785. if (!CheckPermissions(cMyPath, 0, Perms, &smFileNode))
  786. {
  787. pLock->UnlockWrite();
  788. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  789. return FALSE;
  790. }
  791. // Handle unique file name
  792. #define MAX_CNT 20
  793. if (m_pFsys->m_CreateHdr.Flags & CWarFile::UNIQUE_NAME)
  794. {
  795. int Count = -1;
  796. SMEM smIgnore;
  797. for(Count = 0; Count < MAX_CNT; Count++)
  798. {
  799. CString cBuf;
  800. if (Count)
  801. cBuf.Format("%s(%d)", Path, Count);
  802. else
  803. cBuf = Path;
  804. if (!CheckPermissions(cBuf, 0, 0, &smIgnore) && CheckPermissions(cBuf, 0, NODE_WRITE, &smIgnore))
  805. {
  806. cMyPath = cBuf;
  807. smFileNode = smIgnore;
  808. break;
  809. }
  810. }
  811. if (Count == MAX_CNT)
  812. {
  813. pLock->UnlockWrite();
  814. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Can not create unique file name.", Path);
  815. return FALSE;
  816. }
  817. m_pFsys->m_CreateHdr.dwCreationDistribution &= ~(CREATE_ALWAYS | OPEN_EXISTING | OPEN_ALWAYS | TRUNCATE_EXISTING);
  818. m_pFsys->m_CreateHdr.dwCreationDistribution |= CREATE_NEW;
  819. }
  820. // Now, open the file...
  821. FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smFileNode);
  822. HANDLE hNewFileHandle = INVALID_HANDLE_VALUE;
  823. SMEM smParentDir;
  824. smParentDir = 0;
  825. SMEM smFsys;
  826. CString FsysPath;
  827. FILE_SYSTEM *pFsys = NULL;
  828. CDeviceDriver *pDev = NULL;
  829. if (pNode == NULL)
  830. {
  831. // New file.
  832. if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
  833. {
  834. // Get father node
  835. CString ParentPath = cMyPath;
  836. LPSTR p = ParentPath.GetBuffer(1);
  837. p = strrchr(p, '/');
  838. if (p)
  839. {
  840. *p++ = 0;
  841. ParentPath.ReleaseBuffer();
  842. if (!CheckPermissions(ParentPath, NODE_DIR, NODE_WRITE, &smParentDir))
  843. {
  844. pLock->UnlockWrite();
  845. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Not write access to parent dir.", Path);
  846. return FALSE;
  847. }
  848. // Permissions are OK. Now, get ready to create the node
  849. FsysPath = ResolveFsysPath(smParentDir, smFsys);
  850. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
  851. if (!pFsys)
  852. {
  853. pLock->UnlockWrite();
  854. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - No file system on parent dir.", Path);
  855. return FALSE;
  856. }
  857. pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
  858. // Add the original file name to the path
  859. FsysPath += '/';
  860. FsysPath += p;
  861. }
  862. else
  863. {
  864. pLock->UnlockWrite();
  865. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Cant resolve parent dir.", Path);
  866. return FALSE;
  867. }
  868. }
  869. else
  870. {
  871. pLock->UnlockWrite();
  872. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - File don't exist.", Path);
  873. return FALSE;
  874. }
  875. }
  876. else
  877. {
  878. if (pNode->f_Locked || (pNode->f_OpenCnt && (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)))
  879. {
  880. pLock->UnlockWrite();
  881. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - File is open. Access denied.", Path);
  882. return FALSE;
  883. }
  884. FsysPath = ResolveFsysPath(smFileNode, smFsys);
  885. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
  886. pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
  887. if (!pDev || FsysPath.IsEmpty() || !pNode)
  888. {
  889. pLock->UnlockWrite();
  890. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Unresolved internal references.", Path);
  891. return FALSE;
  892. }
  893. if (pNode->f_UseCopy)
  894. {
  895. ASSERT(FALSE); // Not yet implemented
  896. }
  897. }
  898. m_pFsys->m_CreateHdr.pFile->m_hFile = pDev->CreateFile(
  899. FsysPath,
  900. m_pFsys->m_CreateHdr.dwDesiredAccess,
  901. m_pFsys->m_CreateHdr.dwShareMode,
  902. m_pFsys->m_CreateHdr.lpSecurityAttributes,
  903. m_pFsys->m_CreateHdr.dwCreationDistribution,
  904. m_pFsys->m_CreateHdr.dwFlagsAndAttributes,
  905. m_pFsys->m_CreateHdr.hTemplateFile);
  906. if (m_pFsys->m_CreateHdr.pFile->m_hFile == INVALID_HANDLE_VALUE)
  907. {
  908. pLock->UnlockWrite();
  909. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Failed to open file.", cMyPath);
  910. return FALSE;
  911. }
  912. // File opened OK. See if this was a new file
  913. if (smParentDir)
  914. {
  915. DIR_NODE *pDir = NULL;
  916. pNode = NULL;
  917. ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
  918. if (FindNodeFromPath(smFileNode, cMyPath))
  919. {
  920. pNode = (FILE_NODE *)pSmem->__Ptr(smFileNode);
  921. if (pNode)
  922. {
  923. // The new node does not have any valid 'soft' permissions.
  924. // Give the user permission to create the file. We'll be a little
  925. // more restrictive as soon as the file is created :-)
  926. pNode->Perms &= ~NODE_SETTABLE;
  927. pNode->Perms |= 0666;
  928. }
  929. }
  930. if (!CheckPermissions(cMyPath, 0, NODE_WRITE, &smFileNode) || !smFileNode)
  931. {
  932. pDev->CloseHandle(m_pFsys->m_CreateHdr.pFile->m_hFile);
  933. m_pFsys->m_CreateHdr.pFile->m_hFile = INVALID_HANDLE_VALUE;
  934. pLock->UnlockWrite();
  935. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Failed to create file.", FsysPath);
  936. // Delete the node
  937. if (pNode)
  938. {
  939. pNode->f_DeleteFile = TRUE; // Physically erase the file
  940. DeleteNode(smFileNode);
  941. }
  942. return FALSE;
  943. }
  944. if (pNode)
  945. {
  946. // Set permissions
  947. pDir = (DIR_NODE *)pSmem->__Ptr(pNode->Father);
  948. ASSERT(pDir != NULL);
  949. if (pDir && pDir->SpecialNewFilePerm)
  950. {
  951. pNode->Perms &= ~NODE_SETTABLE;
  952. pNode->Perms |= (pDir->SpecialNewFilePerm & NODE_SETTABLE);
  953. }
  954. pNode->Perms &= ~(m_pFsys->m_Umask & NODE_SETTABLE);
  955. if (m_pFsys->m_AssignTo != INVALID_USER_VALUE)
  956. pNode->User = m_pFsys->m_AssignTo;
  957. else
  958. pNode->User = m_pFsys->m_User;
  959. pNode->Class = m_pFsys->m_Class;
  960. if (pDir)
  961. {
  962. // Flush..
  963. pDir->f_Dirty = TRUE;
  964. Flush(pNode->Father);
  965. }
  966. }
  967. }
  968. ASSERT(pNode != NULL);
  969. if (m_pFsys->m_CreateHdr.dwDesiredAccess & GENERIC_WRITE)
  970. {
  971. pNode->f_Locked = TRUE;
  972. }
  973. m_pFsys->m_CreateHdr.pFile->m_DEV = pDev;
  974. m_pFsys->m_CreateHdr.pFile->m_smNode = smFileNode;
  975. // Mark the file as open
  976. pNode->f_OpenCnt++;
  977. pLock->UnlockWrite();
  978. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  979. LogMsg(LOGF_DEBUG,"User opened file %s", FsysPath);
  980. return TRUE;
  981. }
  982. // Change the users working dir
  983. BOOL CFsysThread::DoChDirUser(LPCSTR Path)
  984. {
  985. if (!ChDir(Path))
  986. return FALSE;
  987. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  988. LogMsg(LOGF_DEBUG,"User changed directory to %s", m_pFsys->m_CWD);
  989. return TRUE;
  990. }
  991. // Change the users working dir
  992. BOOL CFsysThread::ChDir(LPCSTR Path)
  993. {
  994. CString cMyPath = Path;
  995. SMEM smNode, smFsys;
  996. if (!ParsePath(cMyPath))
  997. {
  998. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  999. return FALSE;
  1000. }
  1001. ScanPath(cMyPath, FALSE, FALSE, FALSE);
  1002. pLock->ReadLock();
  1003. if (!CheckPermissions(cMyPath, NODE_DIR, NODE_EXEC, &smNode))
  1004. {
  1005. pLock->UnlockRead();
  1006. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1007. return FALSE;
  1008. }
  1009. m_pFsys->m_CWD = cMyPath;
  1010. if (smNode)
  1011. m_pFsys->m_DOSCWD = ResolveFsysPath(smNode, smFsys);
  1012. else
  1013. m_pFsys->m_DOSCWD = "**unresolved**";
  1014. pLock->UnlockRead();
  1015. return TRUE;
  1016. }
  1017. // Command line is parsed. Each token is seperated by ;
  1018. // that is - normally "CMD;arg arg arg"
  1019. BOOL CFsysThread::DoPrepereUserCmdLine(LPCSTR CmdLine)
  1020. {
  1021. CString cBuf;
  1022. BOOL BreakAtSpace;
  1023. m_pFsys->m_FsysPath2.Empty(); // Return buffer
  1024. while(*CmdLine)
  1025. {
  1026. BreakAtSpace = (*CmdLine == '-');
  1027. cBuf = "";
  1028. while(*CmdLine)
  1029. {
  1030. if (BreakAtSpace && (*CmdLine == ' '))
  1031. {
  1032. while(*CmdLine == ' ')
  1033. ++CmdLine;
  1034. break;
  1035. }
  1036. if (*CmdLine == 'n')
  1037. {
  1038. while(*CmdLine == 'n')
  1039. ++CmdLine;
  1040. ++CmdLine;
  1041. break;
  1042. }
  1043. cBuf += *CmdLine++;
  1044. }
  1045. if (!cBuf.IsEmpty())
  1046. {
  1047. if (!BreakAtSpace && (strpbrk(cBuf, "~{[*?")))
  1048. {
  1049. LogMsg(LOGF_WARNINGS,"DoPrepereUserCmdLine(%s) - Pattern matching is not yet implemented.", cBuf);
  1050. }
  1051. else
  1052. {
  1053. if (!m_pFsys->m_FsysPath2.IsEmpty())
  1054. m_pFsys->m_FsysPath2 += 'n';
  1055. m_pFsys->m_FsysPath2 += cBuf;
  1056. }
  1057. }
  1058. }
  1059. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1060. return TRUE;
  1061. }
  1062. // List. This is the full implementation of the UNIX ls command.
  1063. // Create the temporary lists, sort it and write to a tmp file.
  1064. // Return the tmp path to the file in user path 2.
  1065. BOOL CFsysThread::DoList(LPCSTR ArgumentsUnparsed)
  1066. {
  1067. CVfSysLs ls;
  1068. ls.m_pFsysThread = this;
  1069. CCmdArgs UnixArgs;
  1070. LPSTR p = m_pFsys->m_FsysPath1.GetBuffer(1);
  1071. for(p = strtok(p, "n"); p; p = strtok(NULL,"n"))
  1072. UnixArgs.AddArg(p);
  1073. ls.Create(&UnixArgs, CLog::GetLog(), NULL, m_pFsys);
  1074. if (ls.Exec() != 0)
  1075. {
  1076. m_pFsys->m_FsysErrno = FSE_UNIX_ERROR;
  1077. LogMsg(LOGF_WARNINGS,"ls command failed.");
  1078. return FALSE;
  1079. }
  1080. m_pFsys->m_FsysPath1.Empty();
  1081. m_pFsys->m_FsysPath2 = ls.m_TmpName;
  1082. fclose(ls.m_stdio);
  1083. ls.m_stdio = NULL;
  1084. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1085. return TRUE;
  1086. }
  1087. // Native War listing. Place output in 
  1088. // m_pFsys->m_FsysPath2
  1089. BOOL CFsysThread::DoWlist(LPCSTR ArgumentsUnparsed)
  1090. {
  1091. ParsePath(m_pFsys->m_FsysPath1);
  1092. ScanPath(m_pFsys->m_FsysPath1, FALSE, FALSE, FALSE);
  1093. pLock->ReadLock();
  1094. CFileList FileList;
  1095. if (BldFileInfoList(FileList,m_pFsys->m_FsysPath1, TRUE))
  1096. FileList.ListRaw(m_pFsys->m_FsysPath2);
  1097. else
  1098. {
  1099. pLock->UnlockRead();
  1100. m_pFsys->m_FsysErrno = FSE_UNIX_ERROR;
  1101. FileList.Empty();
  1102. return FALSE;
  1103. }
  1104. pLock->UnlockRead();
  1105. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1106. return TRUE;
  1107. }
  1108. BOOL CFsysThread::DoChmod(CCmdArgs& Args)
  1109. {
  1110. CChmod Chmod(this);
  1111. if (!Chmod.Create(&Args, CLog::GetLog(), BUFFER_STDIO, m_pFsys))
  1112. return FALSE;
  1113. Chmod.Exec();
  1114. m_pFsys->m_Output = Chmod.m_stdout;
  1115. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1116. return TRUE;
  1117. }
  1118. // Flush security information
  1119. // Calling layer takes tare of locking...
  1120. void CFsysThread::Flush(SMEM smDir)
  1121. {
  1122. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  1123. if (pDir && pDir->f_Dirty)
  1124. {
  1125. SMEM smFsys;
  1126. CString FsysPath = ResolveFsysPath(smDir, smFsys);
  1127. if (!FsysPath.IsEmpty())
  1128. {
  1129. HANDLE h = CFsysSecurity::OpenSecurityGroupForUpdate(FsysPath);
  1130. if (h != INVALID_HANDLE_VALUE)
  1131. {
  1132. FILE_NODE *pNode;
  1133. DIR_NODE *pThisDir;
  1134. for(pNode = (FILE_NODE *)pSmem->__Ptr(pDir->Son);
  1135. pNode;
  1136. pNode = (FILE_NODE *)pSmem->__Ptr(pNode->Next))
  1137. {
  1138. if (pNode->f_Deleted)
  1139. continue;
  1140. if (pNode->Perms & NODE_DIR)
  1141. pThisDir = (DIR_NODE *)pNode;
  1142. else
  1143. pThisDir = NULL;
  1144. CFsysSecurity::FlushNode(h,
  1145. pNode->Name,
  1146. pNode->Perms & NODE_SETTABLE,
  1147. pNode->User,
  1148. pNode->Class,
  1149. pNode->DlCount,
  1150. pNode->Comment ? pNode->Comment : "",
  1151. pThisDir ? pThisDir->SpecialNewFilePerm : 0);
  1152. }
  1153. CFsysSecurity::CloseSecurityGroup(h);
  1154. pDir->f_Dirty = FALSE;
  1155. }
  1156. }
  1157. }
  1158. }
  1159. BOOL CFsysThread::DoFsysStat()
  1160. {
  1161. pLock->ReadLock();
  1162. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)pSmem->m_Blks[0];
  1163. if (!pSuper)
  1164. return FALSE;
  1165. CString cBuf;
  1166. m_pFsys->m_Output = "VfSys shared memory statistics.n-------------------------------n";
  1167. cBuf.Format("Segments: %d (size=%d) Nodes : %d  Used nodes: %d  Total memory: %d  User memory %dn",
  1168. pSuper->NumUsedSegments,
  1169. pSuper->SegmentSize,
  1170. pSuper->NumNodes,
  1171. pSuper->UsedNodes,
  1172. pSuper->PhysMemory,
  1173. pSuper->UserMemory);
  1174. m_pFsys->m_Output += cBuf;
  1175. m_pFsys->m_Output += "nnVfSys statistics.n-----------------n";
  1176. FILE_SYSTEM *pFsys = (FILE_SYSTEM *)pSmem->__Ptr(*(SMEM *)(&pSmem->m_Segments[0].m_pSMH->pUserPtr[USERPTR_FSYS]));
  1177. while(pFsys)
  1178. {
  1179. cBuf.Format("File system '%s' (%s) FlushDelay=%d copy=%dn", 
  1180. pFsys->Vpath, 
  1181. pFsys->DOSPath,
  1182. pFsys->FlushDelay,
  1183. pFsys->DoCopy);
  1184. m_pFsys->m_Output += cBuf;
  1185. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(pFsys->Next);
  1186. }
  1187. pLock->UnlockRead();
  1188. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1189. return TRUE;
  1190. }
  1191. BOOL CFsysThread::DoCreateDirectory(LPCSTR Path)
  1192. {
  1193. CString cMyPath = Path, FsysPath;
  1194. FILE_SYSTEM *pFsys = NULL;
  1195. CDeviceDriver *pDev = NULL;
  1196. if (!ParsePath(cMyPath))
  1197. {
  1198. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  1199. return FALSE;
  1200. }
  1201. ScanPath(cMyPath, FALSE, FALSE, FALSE);
  1202. pLock->ReadLock();
  1203. if (!CheckPermissions(cMyPath, 0, NODE_WRITE, NULL))
  1204. {
  1205. pLock->UnlockRead();
  1206. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1207. return FALSE;
  1208. }
  1209. // Get the parent dir
  1210. CString ParentDir = cMyPath;
  1211. LPSTR p = ParentDir.GetBuffer(1);
  1212. p = strrchr(p,'/');
  1213. if (!p)
  1214. {
  1215. bad_path:
  1216. pLock->UnlockRead();
  1217. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  1218. return FALSE;
  1219. }
  1220. *p++ = 0;
  1221. ParentDir.ReleaseBuffer();
  1222. if (ParentDir.IsEmpty())
  1223. ParentDir = "/";
  1224. LPCSTR NewName = p;
  1225. if (!*NewName)
  1226. goto bad_path;
  1227. // Get device driver
  1228. SMEM smFsys, smDir;
  1229. if (!FindNodeFromPath(smDir, ParentDir))
  1230. {
  1231. pLock->UnlockRead();
  1232. m_pFsys->m_FsysErrno = FSE_PATH_NOT_FOUND;
  1233. return FALSE;
  1234. }
  1235. FsysPath = ResolveFsysPath(smDir, smFsys);
  1236. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
  1237. pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
  1238. if (!pDev || FsysPath.IsEmpty())
  1239. {
  1240. pLock->UnlockWrite();
  1241. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateDirectory(%s) - Unresolved internal references.", Path);
  1242. return FALSE;
  1243. }
  1244. // Finally, create the directory
  1245. if (FsysPath[FsysPath.GetLength()-1] != '/')
  1246. FsysPath += '/';
  1247. FsysPath += NewName;
  1248. if (!pDev->CreateDirectory || !pDev->CreateDirectory(FsysPath))
  1249. {
  1250. pLock->UnlockRead();
  1251. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1252. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateDirectory(%s) - Failed to create directory. (%s)", 
  1253. Path, FsysPath);
  1254. return FALSE;
  1255. }
  1256. pLock->UnlockRead();
  1257. LogMsg(LOGF_FILEACC,"Created directory '%s' (%s)", Path, FsysPath);
  1258. ScanPath(cMyPath, FALSE, FALSE, TRUE);
  1259. pLock->WriteLock();
  1260. FILE_NODE *pNode;
  1261. DIR_NODE *pDir;
  1262. SMEM smNode;
  1263. if (FindNodeFromPath(smNode, cMyPath))
  1264. {
  1265. pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
  1266. if (pNode)
  1267. {
  1268. // Set permissions
  1269. pNode->Perms |= 0777;
  1270. pDir = (DIR_NODE *)pSmem->__Ptr(pNode->Father);
  1271. ASSERT(pDir != NULL);
  1272. if (pDir && pDir->SpecialNewFilePerm)
  1273. {
  1274. pNode->Perms &= ~NODE_SETTABLE;
  1275. pNode->Perms |= (pDir->SpecialNewFilePerm & NODE_SETTABLE);
  1276. }
  1277. pNode->Perms &= ~(m_pFsys->m_Umask & NODE_SETTABLE);
  1278. if (m_pFsys->m_AssignTo != INVALID_USER_VALUE)
  1279. pNode->User = m_pFsys->m_AssignTo;
  1280. else
  1281. pNode->User = m_pFsys->m_User;
  1282. pNode->Class = m_pFsys->m_Class;
  1283. if (pDir)
  1284. {
  1285. // Flush..
  1286. pDir->f_Dirty = TRUE;
  1287. Flush(pNode->Father);
  1288. }
  1289. }
  1290. }
  1291. pLock->UnlockWrite();
  1292. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1293. return TRUE;
  1294. }
  1295. BOOL CFsysThread::DoDeleteGeneric(LPCSTR Path, DWORD Flags)
  1296. {
  1297. CString cMyPath = Path, FsysPath;
  1298. FILE_SYSTEM *pFsys = NULL;
  1299. CDeviceDriver *pDev = NULL;
  1300. CWarTimer Timer;
  1301. if (!ParsePath(cMyPath))
  1302. {
  1303. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  1304. return FALSE;
  1305. }
  1306. for(; !Timer.TimeOut(1000 * 120); Sleep(1000)) // Try for 2 minues (should be enough for IIS and other shit to close the file...)
  1307. {
  1308. pLock->WriteLock();
  1309. ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
  1310. if (!CheckPermissions(cMyPath, 0, NODE_WRITE, NULL))
  1311. {
  1312. perm_denied:
  1313. pLock->UnlockWrite();
  1314. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1315. return FALSE;
  1316. }
  1317. // Get device driver
  1318. SMEM smFsys, smDir;
  1319. if (!FindNodeFromPath(smDir, cMyPath))
  1320. {
  1321. pLock->UnlockWrite();
  1322. m_pFsys->m_FsysErrno = FSE_PATH_NOT_FOUND;
  1323. return FALSE;
  1324. }
  1325. DIR_NODE *pDir = (DIR_NODE *)pSmem->__Ptr(smDir);
  1326. // Check type
  1327. if (pDir->FileNode.Perms & NODE_DIR) 
  1328. {
  1329. if (!(Flags & DELE_DIR))
  1330. goto perm_denied;
  1331. }
  1332. else if (!(Flags & DELE_FILE))
  1333. goto perm_denied;
  1334. // Check if the file is in use...
  1335. if (pDir->FileNode.f_OpenCnt || pDir->FileNode.f_Locked)
  1336. goto perm_denied; // This can be handled better in the future :-)
  1337. FsysPath = ResolveFsysPath(smDir, smFsys);
  1338. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFsys);
  1339. pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
  1340. if (!pDev || FsysPath.IsEmpty())
  1341. {
  1342. pLock->UnlockWrite();
  1343. LogMsg(LOGF_ERROR,"CFsysThread::DoCreateFile(%s) - Unresolved internal references.", Path);
  1344. return FALSE;
  1345. }
  1346. // Try to delete the file
  1347. if ((pDir->FileNode.Perms & NODE_DIR) && !(pDir->FileNode.Perms & NODE_LINK))
  1348. {
  1349. // This is a bit tricky.. We have to look for .Index.txt and our own security file.
  1350. // If they are the only files in the directory, delete them, and then delete the dir..
  1351. CFileInfo Info;
  1352. CString SearchPath = FsysPath;
  1353. SearchPath += "/*";
  1354. HANDLE h;
  1355. if ((h = pDev->FindFirstFile(SearchPath, Info)) != INVALID_HANDLE_VALUE)
  1356. {
  1357. do
  1358. {
  1359. LPCSTR Name = Info.FileName(); 
  1360. if (!stricmp(Name,".")
  1361. || !stricmp(Name,"..")
  1362. || !stricmp(Name,".Index.txt")
  1363. || !stricmp(Name, SECFILE))
  1364. continue;
  1365. LogMsg(LOGF_DEBUG,"CFsysThread::DoDeleteGeneric(%s) - Directory is not empty.", Path);
  1366. pDev->FindClose(h);
  1367. pLock->UnlockWrite();
  1368. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1369. return FALSE;
  1370. } while(pDev->FindNextFile(h, Info));
  1371. pDev->FindClose(h);
  1372. }
  1373. // Things looks all right... Clean up War files
  1374. {
  1375. CString Target;
  1376. Target = FsysPath;
  1377. Target += "/.Index.txt";
  1378. pDev->DeleteFile(Target);
  1379. Target = FsysPath;
  1380. Target += '/';
  1381. Target += SECFILE;
  1382. pDev->DeleteFile(Target);
  1383. }
  1384. if (pDev->RemoveDirectory(FsysPath))
  1385. {
  1386. pLock->UnlockWrite();
  1387. ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
  1388. LogMsg(LOGF_FILEACC,"Deleted Directory '%s' (%s)", Path, FsysPath);
  1389. break;
  1390. }
  1391. }
  1392. else
  1393. {
  1394. if (pDev->DeleteFile(FsysPath))
  1395. {
  1396. pLock->UnlockWrite();
  1397. ScanPath(cMyPath, FALSE, FALSE, TRUE, FALSE);
  1398. LogMsg(LOGF_FILEACC,"Deleted file '%s' (%s)", Path, FsysPath);
  1399. break;
  1400. }
  1401. }
  1402. pLock->UnlockWrite();
  1403. }
  1404. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1405. return TRUE;
  1406. }
  1407. BOOL CFsysThread::DoCreateLink(LPCSTR From, LPCSTR To)
  1408. {
  1409. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1410. return TRUE;
  1411. }
  1412. BOOL CFsysThread::DoMoveFile(LPCSTR From, LPCSTR To)
  1413. {
  1414. CString FromPath = From, ToPath = To, FsysFromPath, FsysToPath;
  1415. SMEM smFromNode, smToNode, smFromFsys, smToFsys, smToFatherDir;
  1416. CDeviceDriver *pDev = NULL;
  1417. FILE_SYSTEM *pFsys = NULL;
  1418. DIR_NODE *pFatherDir;
  1419. if (!ParsePath(FromPath) || !ParsePath(ToPath))
  1420. {
  1421. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  1422. return FALSE;
  1423. }
  1424. pLock->WriteLock();
  1425. // Check permissions
  1426. ScanPath(FromPath, FALSE, FALSE, TRUE, FALSE);
  1427. ScanPath(ToPath, FALSE, FALSE, TRUE, FALSE);
  1428. if (!CheckPermissions(FromPath, 0, NODE_WRITE, NULL) 
  1429. || !CheckPermissions(ToPath, 0, NODE_WRITE, NULL))
  1430. {
  1431. perm_denied:
  1432. pLock->UnlockWrite();
  1433. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1434. return FALSE;
  1435. }
  1436. // Get from node data
  1437. if (!FindNodeFromPath(smFromNode, FromPath))
  1438. goto perm_denied;
  1439. DIR_NODE *pFromDir = (DIR_NODE *)pSmem->__Ptr(smFromNode);
  1440. ASSERT(pFromDir != NULL);
  1441. if (!pFromDir)
  1442. goto perm_denied;
  1443. // Don't mess with files that are in use...
  1444. if (ScanForBusyFiles(smFromNode))
  1445. goto perm_denied;
  1446. FsysFromPath = ResolveFsysPath(smFromNode, smFromFsys);
  1447. // Get to node data
  1448. if (FindNodeFromPath(smToNode, ToPath))
  1449. {
  1450. DIR_NODE *pToDir = (DIR_NODE *)pSmem->__Ptr(smToNode);
  1451. if ((pToDir->FileNode.Perms & NODE_DIR) == 0)
  1452. goto perm_denied; // Not a directory
  1453. ToPath += '/';
  1454. LPCSTR p = strrchr(FromPath, '/');
  1455. if (!p || !*++p || (*p == '/'))
  1456. goto perm_denied; // Invalid path
  1457. ToPath += p;
  1458. }
  1459. if (FindNodeFromPath(smToNode, ToPath))
  1460. goto perm_denied; // File exist
  1461. // Get the new path's father dir
  1462. CString ToPathFather = ToPath;
  1463. LPSTR p = ToPathFather.GetBuffer(1);
  1464. p = strrchr(p,'/');
  1465. if (p)
  1466. {
  1467. *p = 0;
  1468. if (!*++p || (*p == '/'))
  1469. goto perm_denied; // Invalid path
  1470. }
  1471. else
  1472. goto perm_denied; // Invalid path
  1473. ToPathFather.ReleaseBuffer();
  1474. if (!FindNodeFromPath(smToFatherDir, ToPathFather))
  1475. goto perm_denied; // No father...
  1476. DIR_NODE *pToFatherDir = (DIR_NODE *)pSmem->__Ptr(smToFatherDir);
  1477. if ((pToFatherDir->FileNode.Perms & NODE_DIR) == 0)
  1478. goto perm_denied; // Not a directory
  1479. FsysToPath = ResolveFsysPath(smToFatherDir, smToFsys);
  1480. FsysToPath += '/';
  1481. FsysToPath +=  p;
  1482. // Use origin's file system
  1483. pFsys = (FILE_SYSTEM *)pSmem->__Ptr(smFromFsys);
  1484. pDev = LocalDeviceDrivers[pFsys->DevIdx].pDevDr;
  1485. // See if we can do a simple rename
  1486. if (smToFatherDir == pFromDir->FileNode.Father)
  1487. {
  1488. CString NewName = p, OldName = pFromDir->FileNode.RealName;
  1489. if (NewName.IsEmpty() || OldName.IsEmpty())
  1490. goto perm_denied; // Illegal path
  1491. if (!pDev->MoveFile(FsysFromPath, FsysToPath))
  1492. goto perm_denied; // Permission denied
  1493. ChangeNodeInformation(&pFromDir->FileNode, NewName, NewName, NULL, NULL);
  1494. goto done;
  1495. }
  1496. // Move
  1497. if (!pDev->MoveFile(FsysFromPath, FsysToPath))
  1498. goto perm_denied; // Permission denied
  1499. // Fix permissions
  1500. // Don't use the file system. Relink the node to the new origin dir and
  1501. // save it.
  1502. UnlinkNode(smFromNode);
  1503. LinkToFather(smFromNode, smToFatherDir);
  1504. pFatherDir = (DIR_NODE *)pSmem->__Ptr(smToFatherDir);
  1505. pFatherDir->f_Dirty = TRUE;
  1506. Flush(smToFatherDir);
  1507. done:
  1508. pLock->UnlockWrite();
  1509. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1510. return TRUE;
  1511. }
  1512. BOOL CFsysThread::DoStat(LPCSTR Path)
  1513. {
  1514. CString cMyPath = Path;
  1515. SMEM smNode;
  1516. if (!ParsePath(cMyPath))
  1517. {
  1518. m_pFsys->m_FsysErrno = FSE_BAD_PATH;
  1519. return FALSE;
  1520. }
  1521. ScanPath(cMyPath, FALSE, FALSE, FALSE);
  1522. pLock->ReadLock();
  1523. if (!CheckPermissions(cMyPath, 0, NODE_READ, &smNode))
  1524. {
  1525. perm_denied:
  1526. pLock->UnlockRead();
  1527. m_pFsys->m_FsysErrno = FSE_PERMISSION_DENIED;
  1528. return FALSE;
  1529. }
  1530. FILE_NODE *pNode = (FILE_NODE *)pSmem->__Ptr(smNode);
  1531. if (!pNode)
  1532. {
  1533. ASSERT(FALSE);
  1534. goto perm_denied;
  1535. }
  1536. m_pFsys->m_FileLen = pNode->Size;
  1537. m_pFsys->m_FileTime = pNode->LastWriteDate;
  1538. m_pFsys->m_FilePerms = pNode->Perms;
  1539. pLock->UnlockRead();
  1540. ::PostMessage(m_CallbackWin, FSM_CALLBACK, (WPARAM)m_pFsys, 0);
  1541. return TRUE;
  1542. }