Fsys.cpp
资源名称:warftpd.zip [点击查看]
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:29k
源码类别:
Ftp客户端
开发平台:
Visual C++
- // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
- // Copyright 1996 by Jarle Aase. All rights reserved.
- // See the "War Software Series Licende Agreement" for details concerning
- // use and distribution.
- // ---
- // This source code, executables and programs containing source code or
- // binaries or proprietetary technology from the War Software Series are
- // NOT alloed used, viewed or tested by any governmental agencies in
- // any countries. This includes the government, departments, police,
- // military etc.
- // ---
- // This file is intended for use with Tab space = 2
- // Created and maintained in MSVC Developer Studio
- // ---
- // NAME : Fsys.cpp
- // PURPOSE : Simple file system (when not running VfSys)
- // PROGRAM :
- // DATE : Sept. 27 1996
- // AUTHOR : Jarle Aase
- // ---
- // REVISION HISTORY
- //
- #include "stdafx.h"
- #include <sys/stat.h>
- #include "WarDaemon.h"
- #include "FsysSecurity.h"
- #include "ctype.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- // Note: All functions on this level works with paths like:
- // <DRIVE><PATH><PATH>
- // where <DRIVE> is a one letter character representing the drive.
- // An empty path "" represents the root on the lowest level.
- // On the higher levels (return to user functions, the root is always ...
- // No functions return trailing .
- CFsys *CFsys::m_pCFsys = NULL;
- CLog *CFsys::m_Log = NULL;
- CFsys::CFsys()
- {
- m_pCFsys = this;
- }
- CFsys::~CFsys()
- {
- m_pCFsys = NULL;
- }
- LPCSTR CFsys::VisualPath(LPCSTR RootPath, LPCSTR Path, LPSTR ReturnBuf, int BufLen)
- {
- char buf[MAX_PATH * 2];
- LPSTR p = buf;
- int PathLen = 0;
- ASSERT(AfxIsValidString(Path));
- ASSERT(AfxIsValidString(RootPath));
- ASSERT(AfxIsValidAddress(ReturnBuf,BufLen));
- ASSERT(BufLen >= MAX_PATH);
- // See if we have to map away the root path
- int RootPathLen = strlen(RootPath);
- if (!strnicmp(RootPath,Path,RootPathLen))
- Path += RootPathLen;
- if (*Path != '\')
- {
- *p++ = '/';
- ++PathLen;
- }
- while(*Path)
- {
- if (++PathLen >= (sizeof(buf) - 1))
- {
- LogMsg(LOGF_WARNINGS,"VisualPath(): Internal working buffer is too small (%d bytes).", sizeof(buf));
- return("CFsys::VisualPath(): Error, working buffer is too small.");
- }
- if (*Path == '\')
- {
- *p++ = '/';
- ++Path;
- }
- else
- *p++ = *Path++;
- }
- *p = 0;
- if (PathLen > BufLen)
- {
- LogMsg(LOGF_WARNINGS,"VisualPath(): Return buffer is too small (%d bytes).", BufLen);
- return("CFsys::VisualPath(): Error, return buffer is too small.");
- }
- memcpy(ReturnBuf, buf, PathLen + 1);
- ASSERT(AfxIsValidString(ReturnBuf));
- return ReturnBuf;
- }
- BOOL CFsys::Create(CLog *Log)
- {
- ASSERT(this != NULL);
- m_Log = Log;
- return TRUE;
- }
- void CFsys::LogMsg(int flag, LPCSTR Format, ...)
- {
- CString cBuf;
- if (!ShouldLog(m_Log, flag))
- return;
- ASSERT(AfxIsValidString(Format, FALSE));
- ASSERT(m_Log != NULL);
- ASSERT(AfxIsValidAddress(m_Log,sizeof(CLog)));
- cBuf.Format("CFsys: %s", Format);
- va_list argList;
- va_start(argList, Format);
- m_Log->LogMsgV(flag, cBuf, argList);
- va_end(argList);
- }
- BOOL CFsys::PrepereCommandLine(CCmdArgs& Args, LPCSTR RootDir, LPCSTR CWD, int User, ...)
- {
- va_list argList;
- va_start(argList, User);
- LPCSTR LineArg;
- LPSTR buf, p;
- LPCSTR Tok;
- LPSTR TokBuf;
- char MyBuf[1024];
- int TokLen;
- for(;;)
- {
- LineArg = va_arg(argList, LPCSTR);
- if (!LineArg)
- break;
- ASSERT(AfxIsValidString(LineArg));
- // See if we can use the stack buffer...
- // If it is too small, allocate a buffer...
- TokLen = strlen(LineArg);
- if (TokLen > (sizeof(MyBuf) -1))
- p = TokBuf = buf = strdup(LineArg);
- else
- {
- buf = NULL;
- memcpy(MyBuf,LineArg,TokLen);
- MyBuf[TokLen] = 0;
- p = TokBuf = MyBuf;
- }
- for(;;)
- {
- // If a parameter begins with '-' we assume a line parameter and brak at space,
- // else we take the entire line...
- if (*p == '-')
- Tok = " ";
- else
- Tok = "";
- if ((p = strtok(TokBuf,Tok)) == NULL)
- break;
- TokBuf = NULL;
- // Expand file name, unless it is a line parameter
- if (!*Tok && strpbrk(p, "~{[*?") != NULL)
- {
- // Add file names from pattern...
- if (AddFromPattern(Args, RootDir, CWD, User, p));
- }
- else
- Args.AddArg(p);
- }
- // We will use the stack buffer in most cases
- if (buf)
- delete buf;
- }
- va_end(argList);
- return TRUE;
- }
- int CFsys::AddFromPattern(CCmdArgs& Args, LPCSTR RootDir, LPCSTR CWD, int User, LPCSTR p)
- {
- HANDLE h;
- WIN32_FIND_DATA Data;
- CString cPatternPath;
- int Rval = 0;
- // TODO: Check user access before adding a path
- // Path is relative to current dir.
- // TODO: Map the CWD to real path (in case of links, /, ../ etc..)
- cPatternPath.Format("%s\%s", CWD, p);
- if ((h = FindFirstFile(User, cPatternPath, &Data)) != INVALID_HANDLE_VALUE)
- {
- do
- {
- ++Rval;
- Args.AddArg(Data.cFileName);
- } while(FindNextFile(h, &Data));
- FindClose(h);
- }
- return Rval;
- }
- HANDLE CFsys::FindFirstFile(int User, LPCSTR Path, LPWIN32_FIND_DATA Data)
- {
- CFindFileHandle *MyHandle = (CFindFileHandle *)INVALID_HANDLE_VALUE;
- HANDLE h;
- HANDLE SecurityGrp = INVALID_HANDLE_VALUE;
- ASSERT(AfxIsValidString(Path));
- char UsePath[MAX_PATH];
- char MyPath[MAX_PATH];
- char MyPattern[MAX_PATH];
- // Get the pattern.
- strcpy(UsePath,Path);
- LPSTR pattern = strrchr(UsePath,'\');
- if (pattern && strpbrk(pattern,"*?"))
- {
- strcpy(MyPattern,pattern + 1);
- if (pattern == UsePath)
- ++pattern; // Root path, move beoind and terminate string
- *pattern = 0;
- }
- else
- {
- // No pattern.
- *MyPattern = 0;
- }
- if (*Path == '$')
- *UsePath = *MyPath = *MyPattern = 0; // Special case - root node
- else if (!RealPath(UsePath,MyPath))
- return INVALID_HANDLE_VALUE;
- if (!*MyPattern)
- {
- // We *must* have a pattern to get the security right..
- if ((pattern = strrchr(MyPath,'\')) != NULL)
- {
- *pattern++ = 0;
- strcpy(MyPattern,pattern);
- }
- }
- if (User)
- {
- // We only do security lookup for users. 0 is the system. It has full access
- // Also, we need the security descriptor of the parent directory in order to
- // verify the files in this dir.
- if ((SecurityGrp = CFsysSecurity::GetSecurityGroupFromPath(
- User, CUsr::GetUserClass(User), MyPath)) == INVALID_HANDLE_VALUE)
- {
- LogMsg(LOGF_DEBUG,"FindFirstFile(%s) - failed.", Path);
- //free(xpath);
- return INVALID_HANDLE_VALUE;
- }
- }
- if ((strlen(MyPath) + strlen(MyPattern)) < 3)
- {
- MyHandle = new CFindFileHandle;
- MyHandle->m_User = User;
- MyHandle->m_Pattern = MyPattern;
- MyHandle->m_PathsQueued = new CCmdArgs;
- MyHandle->m_FullPath = "\";
- MyHandle->m_SecurityHandle = SecurityGrp;
- if (!*MyPattern && !*MyPath)
- {
- //Special case. Return directory . in path ...
- MyHandle->m_PathsQueued->AddArg(".");
- PrepereLogicalFile(MyHandle->m_PathsQueued->Arg(MyHandle->m_Argc++), Data);
- }
- else
- {
- // Special case. We have to "manifacture" a list of disk drives as if they were files...
- char *p;
- if (!*MyPattern)
- {
- // Dos drives will be listed as "C:" after RealPath() is done
- *MyPattern = MyPath[1];
- MyPattern[1] = 0;
- }
- MyPath[0] = '.';
- MyPath[1] = 0;
- GetLogicalDriveStrings(MAX_PATH, MyPath + 2);
- if (MyPattern[1])
- goto failure; // Drive can only be 1 character long...
- // Convert to valid path
- for(p = MyPath;;)
- {
- if (!*p && !*(p+1))
- break;
- if (!*p && *(p+1))
- *p = ';';
- ++p;
- }
- for (p = strtok(MyPath,";:\"); p && *p; p = strtok(NULL,";:\"))
- {
- if ((*MyPattern == '*') || (*MyPattern == '?') || (toupper(*MyPattern) == toupper(*p)))
- MyHandle->m_PathsQueued->AddArg(p);
- }
- if (MyHandle->m_PathsQueued->m_argc)
- PrepereLogicalFile(MyHandle->m_PathsQueued->Arg(MyHandle->m_Argc++), Data);
- else
- {
- failure:
- delete MyHandle;
- MyHandle = (CFindFileHandle *)INVALID_HANDLE_VALUE;
- }
- }
- }
- else
- {
- // Default processing
- if (*MyPattern)
- sprintf(MyPath + strlen(MyPath), "\%s", MyPattern);
- DosPath(MyPath);
- if (*MyPath == '\')
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- LogMsg(LOGF_DEBUG, "FindFirstFile() - Invalid DOS path %s", MyPath);
- return INVALID_HANDLE_VALUE;
- }
- if ((h = ::FindFirstFile(MyPath, Data)) != INVALID_HANDLE_VALUE)
- {
- MyHandle = new CFindFileHandle;
- MyHandle->m_DOShandle = h;
- MyHandle->m_User = User;
- MyHandle->m_Pattern = MyPattern;
- MyHandle->m_FullPath = MyPath;
- MyHandle->m_SecurityHandle = SecurityGrp;
- }
- }
- return (HANDLE) MyHandle;
- }
- BOOL CFsys::FindNextFile(HANDLE h, LPWIN32_FIND_DATA Data)
- {
- ASSERT(AfxIsValidAddress(Data, sizeof(LPWIN32_FIND_DATA)));
- CFindFileHandle *MyHandle = (CFindFileHandle *)h;
- ASSERT(AfxIsValidAddress(MyHandle, sizeof(CFindFileHandle)));
- if (MyHandle->m_DOShandle != INVALID_HANDLE_VALUE)
- return ::FindNextFile(MyHandle->m_DOShandle, Data);
- ASSERT(AfxIsValidAddress(MyHandle, sizeof(CFindFileHandle)));
- if (MyHandle->m_Argc < MyHandle->m_PathsQueued->m_argc)
- {
- PrepereLogicalFile(MyHandle->m_PathsQueued->Arg(MyHandle->m_Argc++), Data);
- return TRUE;
- }
- else
- return FALSE;
- }
- BOOL CFsys::FindClose(HANDLE h)
- {
- CFindFileHandle *MyHandle = (CFindFileHandle *)h;
- BOOL Rval = TRUE;
- ASSERT(AfxIsValidAddress(MyHandle, sizeof(CFindFileHandle)));
- if (MyHandle->m_DOShandle != INVALID_HANDLE_VALUE)
- {
- Rval = ::FindClose(MyHandle->m_DOShandle);
- MyHandle->m_DOShandle = INVALID_HANDLE_VALUE;
- }
- delete MyHandle;
- return Rval;
- }
- // Put dummy data into Data
- void CFsys::PrepereLogicalFile(LPCSTR Name, LPWIN32_FIND_DATA Data)
- {
- ASSERT(AfxIsValidString(Name));
- ASSERT(AfxIsValidAddress(Data, sizeof(LPWIN32_FIND_DATA)));
- Data->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
- GetSystemTimeAsFileTime(&Data->ftCreationTime);
- GetSystemTimeAsFileTime(&Data->ftLastAccessTime);
- GetSystemTimeAsFileTime(&Data->ftLastWriteTime);
- Data->nFileSizeHigh = 0;
- Data->nFileSizeLow = 512; // Just say 512 bytes... Most likely a directory...
- strcpy(Data->cFileName, Name);
- }
- // Make a path.
- LPCSTR CFsys::MkPath(LPCSTR Root, LPCSTR CWD, LPCSTR Path, LPSTR buf)
- {
- LPCSTR BeginPath = CWD;
- LPSTR p = buf;
- BOOL CheckSlash;
- int cnt = 0;
- ASSERT(AfxIsValidString(CWD));
- ASSERT(AfxIsValidString(Path));
- ASSERT(AfxIsValidString(Root));
- ASSERT(AfxIsValidAddress(buf,MAX_PATH));
- if (*Root && *Path == '\')
- {
- BeginPath = Root;
- ++Path;
- }
- CheckSlash = *BeginPath != 0;
- while(*BeginPath)
- {
- if (++cnt >= MAX_PATH)
- goto cnt_fail;
- *p++ = *BeginPath++;
- ASSERT(AfxIsValidAddress(p,1));
- }
- if (CheckSlash && (p[-1] != '\'))
- {
- if (++cnt >= MAX_PATH)
- goto cnt_fail;
- *p++ = '\';
- ASSERT(AfxIsValidAddress(p,1));
- }
- while(*Path)
- {
- if (++cnt >= MAX_PATH)
- goto cnt_fail;
- *p++ = *Path++;
- ASSERT(AfxIsValidAddress(p,1));
- }
- if (cnt && (p[-1] == '\'))
- --p; // Remove trailing ...
- *p = 0;
- return buf;
- cnt_fail:
- ASSERT(cnt >= MAX_PATH);
- LogMsg(LOGF_WARNINGS,"MkPath() - Buffer overflow. Path must be less than %d bytes.", MAX_PATH);
- buf[--cnt] = 0; // Just in case...
- return NULL;
- }
- // Parse a path and return the actual DOS path
- // Resolve links (.lnk files and VfSys links)
- // The returned path is either C:, C:whatever or (sytstem root)
- LPCSTR CFsys::RealPath(LPCSTR Path, LPSTR Buf, BOOL DotsOnly)
- {
- ASSERT(AfxIsValidString(Path));
- ASSERT(AfxIsValidAddress(Buf,MAX_PATH));
- LPCSTR PathSave = Path;
- int cnt = 0;
- struct _stat st;
- if (!*Path || !strcmp(Path,"\") || !strcmp(Path,"\."))
- {
- *Buf = 0;
- return Buf; // Special case - system root path.
- }
- if ((*Path != '\') && (*Path != '/'))
- return FALSE;
- while(*Path)
- {
- if ((*Path == '\') || (*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 ..\ ", PathSave);
- return NULL;
- }
- while(--cnt && (Buf[cnt] != '\') && (Buf[cnt] != '/'))
- {
- ASSERT(cnt >= 0);
- }
- Path += 3;
- continue;
- }
- }
- }
- if (!DotsOnly && Path[1] && (cnt > 3))
- {
- // The path *must* be a directory. Check with file system.
- Buf[cnt] = 0;
- if (_stat(DosPath(Buf),&st))
- {
- LogMsg(LOGF_DEBUG,"RealPath(%s) - stat() failed on directory '%s'.", PathSave, Buf);
- return NULL;
- }
- if (!(st.st_mode & _S_IFDIR))
- {
- // TODO: Add link support
- LogMsg(LOGF_DEBUG,"RealPath(%s) - %s: not a directory", PathSave, Buf);
- return NULL;
- }
- UnixPath(Buf);
- }
- }
- // Default
- if (*Path == '/')
- {
- Buf[cnt] = '\';
- ++Path;
- }
- else
- Buf[cnt] = *Path++;
- if (++cnt >= MAX_PATH)
- {
- LogMsg(LOGF_WARNINGS,"RealPath(%s) - Real path exeeds limit of %d bytes.", PathSave, MAX_PATH);
- Buf[--cnt] = 0; // Just in case ...
- return NULL;
- }
- }
- Buf[cnt] = 0;
- return Buf;
- }
- // Convert C style paths to C: ...
- LPCSTR CFsys::DosPath(LPSTR Path)
- {
- ASSERT(AfxIsValidString(Path));
- if ((Path[0] == '\') && isalpha(Path[1]) && (!Path[2] || (Path[2] == '\')))
- {
- ASSERT((*Path == '\') || (*Path == '/') || (Path[1] == ':'));
- Path[0] = Path[1];
- Path[1] = ':';
- }
- return Path;
- }
- // Convert C: style paths to C ...
- LPCSTR CFsys::UnixPath(LPSTR Path)
- {
- ASSERT(AfxIsValidString(Path));
- if (*Path && Path[1] == ':')
- {
- Path[1] = Path[0];
- Path[0] = '\';
- }
- return Path;
- }
- HANDLE CFsys::CreateFile(LPCTSTR lpFileName, // pointer to name of the file
- DWORD dwDesiredAccess, // access (read-write) mode
- DWORD dwShareMode, // share mode
- LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security descriptor
- DWORD dwCreationDistribution, // how to create
- DWORD dwFlagsAndAttributes, // file attributes
- HANDLE hTemplateFile // handle to file with attributes to copy
- )
- {
- ASSERT(AfxIsValidString(lpFileName));
- CString cFileName = lpFileName;
- DosPath(cFileName.GetBuffer(MAX_PATH));
- cFileName.ReleaseBuffer();
- ASSERT(AfxIsValidString(lpFileName));
- return ::CreateFile(cFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
- dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile);
- }
- ///////////////////////////////////////////////////////////////////////////
- // Build a CFileInfoList
- BOOL CFsys::BldFileInfoList(int User, LPCSTR Root, CFileInfoList& FileList, LPCSTR Origin, LPCSTR Path, BOOL ListDir)
- {
- char buf[MAX_PATH];
- MkPath(Root, Origin, Path, buf);
- int Len = strlen(buf);
- if (ListDir)
- {
- // If Len == 0 we have the root.
- // MkPath will ensure that is removed from the end of any other path.
- strcpy(buf + Len, Len == 1 ? "*" : "\*");
- if (!AddFileInfoListPath(User, FileList, buf))
- {
- buf[Len] = 0;
- AddFileInfoListPath(User, FileList, buf);
- }
- }
- else
- AddFileInfoListPath(User, FileList, buf);
- return TRUE;
- }
- int CFsys::AddFileInfoListPath(int User, CFileInfoList& FileList, LPCSTR Path)
- {
- /*
- HANDLE h;
- CFileInfo *Info;
- WIN32_FIND_DATA Data;
- */
- int Count = 0;
- CFsysSecurityNode *fsn = NULL;
- USER Class = CUsr::GetUserClass(User);
- /*
- if ((h = FindFirstFile(User, Path, &Data)) != INVALID_HANDLE_VALUE)
- {
- do
- {
- ASSERT(AfxIsValidString(((CFindFileHandle *)h)->m_FullPath));
- FileList.m_FullPath = ((CFindFileHandle *)h)->m_FullPath;
- ++Count;
- Info = new CFileInfo;
- memcpy(&Info->m_Data, &Data, sizeof(WIN32_FIND_DATA));
- int Mask;
- fsn = NULL;
- Info->m_Flags = CFsysSecurity::GetPermissions(
- User,
- Class,
- GetSecurityHandle(h),
- Data.cFileName,
- ((Info->m_Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0),
- &Mask, // Unused here...
- &fsn,
- TRUE);
- Info->m_Flags |= (Info->m_Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
- NODE_DIR : 0;
- if ((Path[0] == '\') && (Path[1] == '*') && !Path[2])
- Info->m_Flags |= NODE_DRIVE; // Quick patch for drives...
- if (Info->m_Data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- {
- Info->m_Flags |= NODE_READONLY;
- Info->m_Flags &= ~(NODE_0WRITE | NODE_AWRITE | NODE_GWRITE);
- }
- if (fsn)
- {
- Info->m_User = fsn->Owner;
- Info->m_Group = fsn->Class;
- Info->m_Comment = strdup(fsn->Comment);
- }
- else
- {
- Info->m_User = 0;
- Info->m_Group = 0;
- Info->m_Comment.Empty();
- }
- if ((Info->m_Data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- || (Info->m_User && ((User == Info->m_User) && (Info->m_Flags & NODE_OHIDE)))
- || (Info->m_Group && ((Class == Info->m_Group) && (Info->m_Flags & NODE_GHIDE)))
- || (Info->m_Flags & NODE_AHIDE))
- {
- Info->Hide(TRUE);
- }
- Info->m_Inode = 0;
- Info->m_FileNameLen = strlen(Info->m_Data.cFileName);
- Info->m_Links = 1;
- FileList.Add(Info);
- } while(FindNextFile(h,&Data));
- FindClose(h);
- }
- */
- return Count;
- }
- // Get a handle to Find*File() handle and return the security handle
- HANDLE CFsys::GetSecurityHandle(HANDLE h)
- {
- CFindFileHandle *MyHandle = (CFindFileHandle *)h;
- ASSERT(AfxIsValidAddress(MyHandle, sizeof(CFindFileHandle)));
- ASSERT(AfxIsValidAddress((LPVOID)MyHandle->m_SecurityHandle, sizeof(CFsysSecurityGrp)));
- return MyHandle->m_SecurityHandle;
- }
- BOOL CFsys::IsDirectory(int User, LPCSTR Path)
- {
- HANDLE h;
- WIN32_FIND_DATA Data;
- if ((h = FindFirstFile(User, Path, &Data)) != INVALID_HANDLE_VALUE)
- {
- FindClose(h);
- return (Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
- }
- return FALSE;
- }
- BOOL CFsys::IsPlainFile(int User, LPCSTR Path)
- {
- HANDLE h;
- WIN32_FIND_DATA Data;
- if ((h = FindFirstFile(User, Path, &Data)) != INVALID_HANDLE_VALUE)
- {
- FindClose(h);
- return (Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
- }
- return FALSE;
- }
- // General file security checker.
- // Called prior to reading/creating files or directories
- BOOL CFsys::CheckPermission(int User, LPCSTR RootPath, LPCSTR Path, BOOL IsDir, int PermsWanted)
- {
- ASSERT(AfxIsValidString(Path));
- HANDLE h;
- WIN32_FIND_DATA Data;
- SetLastError(NO_ERROR);
- // EXT module
- CHKPRMS cp;
- cp.User = User;
- cp.RootPath = RootPath;
- cp.IsDir = IsDir;
- cp.PermsWanted = PermsWanted;
- int err;
- if (err = PrcExt(CAPIHandler::OnFsysCheckPermission,0,(WPARAM)0,(LPARAM)&cp))
- {
- if (err == CFuncList::AbortError)
- return FALSE;
- if (err == CFuncList::OkAllDone)
- return TRUE;
- }
- // Check against root path
- if (User)
- {
- CString cPath, cBuf;
- if (!RootPath)
- RootPath = CUsr::GetRecursiveParam(User, "Root", "", cBuf);
- if (!RootPath || !*RootPath)
- {
- LPCSTR Name = CUsr::FindUser(User,cBuf);
- if (!Name)
- Name = "**unknown**";
- LogMsg(LOGF_WARNINGS,"CFsys::CheckPermission(%s) - User has no root dir! Permission denied.", Name);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- LPCSTR p = Path;
- while(*p && (*p == *RootPath))
- {
- ++p;
- ++RootPath;
- }
- if (*Path && *RootPath)
- {
- LPCSTR Name = CUsr::FindUser(User,cBuf);
- if (!Name)
- Name = "**unknown**";
- LogMsg(LOGF_DEBUG,"CFsys::CheckPermission(%s '%s') - Path is above the users root path. Permission denied.", Name, Path);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- }
- // See if the file/dir exist. If so, we just check that objects permissions..
- if ((h = FindFirstFile(User, Path, &Data)) != INVALID_HANDLE_VALUE)
- {
- // The object exist.
- BOOL Rval = CFsysSecurity::CheckPermission(
- User,
- CUsr::GetUserClass(User),
- GetSecurityHandle(h),
- Data.cFileName,
- PermsWanted,
- IsDir);
- FindClose(h);
- if (!Rval)
- {
- LogMsg(LOGF_DEBUG,"CheckPermission(%s) - CheckPermission() - Permission denied.", Path);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- // If the user want to create a new object we must also check the parent dir
- if (!(PermsWanted & NODE_CREATE))
- return TRUE;
- }
- // If the user want read access, we can give up now.
- if (PermsWanted & (NODE_READ | NODE_EXEC))
- {
- LogMsg(LOGF_DEBUG,"CheckPermission(%s) - File/dir not found (or access denied).", Path);
- SetLastError(ERROR_FILE_NOT_FOUND);
- return FALSE;
- }
- // The object dont exist...
- // Check for appropriate permission on the parent directory level
- CString cMyPath = Path;
- LPSTR p = strrchr(cMyPath.GetBuffer(1),'\');
- if (!p)
- {
- LogMsg(LOGF_DEBUG,"CheckPermission(%s) - Invalid path.", Path);
- SetLastError(ERROR_BAD_FORMAT);
- return FALSE;
- }
- *p = 0;
- cMyPath.ReleaseBuffer();
- if ((h = FindFirstFile(User, cMyPath, &Data)) == INVALID_HANDLE_VALUE)
- {
- LogMsg(LOGF_DEBUG,"CheckPermission(%s) - Parent directory not found.", Path);
- SetLastError(ERROR_PATH_NOT_FOUND);
- return FALSE;
- }
- if (!CFsysSecurity::CheckPermission(
- User,
- CUsr::GetUserClass(User),
- GetSecurityHandle(h),
- Data.cFileName,
- PermsWanted,
- TRUE))
- {
- FindClose(h);
- LogMsg(LOGF_DEBUG,"CheckPermission(%s) - CheckPermission() - Permission denied on parent level.", Path);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- FindClose(h);
- return TRUE;
- }
- // Change directory.
- // Path is any valid path, including unresolved links and ..'s
- // Path must have / mapped to , and begin with ...
- int CFsys::chdir(int User, LPCSTR Root, CString& cCWD, LPCSTR Path)
- {
- ASSERT(AfxIsValidString(Root));
- ASSERT(AfxIsValidString(cCWD));
- ASSERT(AfxIsValidString(Path));
- char MyPath[MAX_PATH];
- char ParsedPath[MAX_PATH];
- MkPath(Root, cCWD, Path, MyPath);
- ASSERT(AfxIsValidString(MyPath));
- // Map ../ etc for the path...
- if (!RealPath(MyPath, ParsedPath, TRUE))
- {
- LogMsg(LOGF_WARNINGS,"chdir(%s) - Unexpected error in RealPath(%s).", Path, MyPath);
- return -1;
- }
- // Check permissions
- if (!CheckPermission(User, Root, ParsedPath, TRUE, NODE_EXEC))
- {
- LogMsg(LOGF_DEBUG,"chdir(%s) - Not a directory (or no access).", MyPath);
- return -1;
- }
- UnixPath(ParsedPath);
- ASSERT(AfxIsValidString(ParsedPath));
- cCWD = ParsedPath;
- return 0;
- }
- LPCSTR CFsys::GetFullPath(int User, LPCSTR Root, LPCSTR CWD, LPCSTR Path, CString& cBuf, DWORD AccessFlags)
- {
- ASSERT(AfxIsValidString(Root));
- ASSERT(AfxIsValidString(CWD));
- ASSERT(AfxIsValidString(Path));
- char MyPath[MAX_PATH];
- char ParsedPath[MAX_PATH];
- MkPath(Root, CWD, Path, MyPath);
- ASSERT(AfxIsValidString(MyPath));
- // Map ../ etc for the path...
- if (!RealPath(MyPath, ParsedPath, TRUE))
- {
- LogMsg(LOGF_WARNINGS,"GetFullPath(%s) - Unexpected error in RealPath(%s).", Path, MyPath);
- return NULL;
- }
- UnixPath(ParsedPath);
- ASSERT(AfxIsValidString(ParsedPath));
- cBuf = ParsedPath;
- return cBuf;
- }
- BOOL CFsys::RenamePath(int User, LPCSTR OldPath, LPCSTR NewPath)
- {
- ASSERT(AfxIsValidString(OldPath));
- ASSERT(AfxIsValidString(NewPath));
- BOOL IsDir = IsDirectory(User, OldPath);
- if (!CheckPermission(User, NULL, OldPath, IsDir, NODE_WRITE))
- {
- LogMsg(LOGF_DEBUG,"RenamePath(%s --> %s) - Missing WRITE permission to old path.",
- OldPath, NewPath);
- return FALSE;
- }
- if (!CheckPermission(User, NULL, NewPath, IsDir, NODE_CREATE))
- {
- LogMsg(LOGF_DEBUG,"RenamePath(%s --> %s) - Missing CREATE permission to new path.",
- OldPath, NewPath);
- return FALSE;
- }
- // Convert filenames to DOS style names
- CString cOldPath = OldPath;
- CString cNewPath = NewPath;
- DosPath(cOldPath.GetBuffer(MAX_PATH));
- DosPath(cNewPath.GetBuffer(MAX_PATH));
- cNewPath.ReleaseBuffer();
- cOldPath.ReleaseBuffer();
- ASSERT(AfxIsValidString(cOldPath));
- ASSERT(AfxIsValidString(cNewPath));
- if (!::MoveFileEx(cOldPath, cNewPath, MOVEFILE_WRITE_THROUGH))
- {
- LogMsg(LOGF_DEBUG,"RenamePath() - MoveFileEx(%s, %s) failed. %s", cOldPath, cNewPath,
- GetLastErrorText());
- return FALSE;
- }
- return TRUE;
- }
- // Delete a file or directory (if the dir is empty)
- BOOL CFsys::DeletePath(int User, LPCSTR Path)
- {
- ASSERT(AfxIsValidString(Path));
- if (strpbrk(Path,"*?[]{}"))
- {
- LogMsg(LOGF_WARNINGS,"DeletePath(%s) - not allowed to delete paths containing patterns.", Path);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- CString cMyPath = Path;
- // Check permissions
- BOOL IsDir;
- IsDir = IsDirectory(User, Path);
- if (!CheckPermission(User, NULL, Path, IsDir, NODE_WRITE))
- {
- LogMsg(LOGF_WARNINGS,"DeletePath(%s) - Permission denied", Path);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- // Convert filename to DOS style names
- DosPath(cMyPath.GetBuffer(1));
- cMyPath.ReleaseBuffer();
- ASSERT(AfxIsValidString(cMyPath));
- if (IsDir)
- {
- return ::RemoveDirectory(cMyPath);
- }
- return ::DeleteFile(cMyPath);
- }
- // Create a new directory
- BOOL CFsys::MkDir(int User, LPCSTR Path)
- {
- ASSERT(AfxIsValidString(Path));
- if (strpbrk(Path,"*?[]{}"))
- {
- LogMsg(LOGF_WARNINGS,"MkDir(%s) - not allowed to create paths containing patterns.", Path);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- CString cMyPath = Path;
- // Check permissions
- if (!CheckPermission(User, NULL, Path, TRUE, NODE_CREATE))
- {
- LogMsg(LOGF_WARNINGS,"MkDir(%s) - Permission denied", Path);
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- // Convert filename to DOS style names
- DosPath(cMyPath.GetBuffer(MAX_PATH));
- cMyPath.ReleaseBuffer();
- ASSERT(AfxIsValidString(cMyPath));
- return ::CreateDirectory(cMyPath, NULL);
- }
- // Chmod on a single file
- // Return 0 on success
- int CFsys::chmod(int User, LPCSTR Path, int SetMode, int SetOwner,
- int SetClass, LPCSTR SetComment, int DefDirMode, int DefFileMode)
- {
- LPSTR fpath;
- LPSTR MyPath = strdup(Path);
- HANDLE SecurityGrp = INVALID_HANDLE_VALUE, SecurityDsc;
- int rval = 0;
- CFsysSecurityNode *fsn = NULL;
- DosPath(MyPath);
- DWORD dw = GetFileAttributes(MyPath);
- BOOL IsDir = ((dw != 0xFFFFFFFF) && (dw & FILE_ATTRIBUTE_DIRECTORY));
- // Remove any trailing on the path..
- strcpy(MyPath,Path);
- LPSTR p = MyPath + strlen(MyPath) - 1;
- if (*p == '\')
- *p = 0;
- // Get the parent dir
- fpath = strrchr(MyPath,'\');
- if (!fpath)
- {
- rval = -1;
- goto done;
- }
- *fpath++ = 0;
- CFsysSecurity::Lock();
- if ((SecurityGrp = CFsysSecurity::GetSecurityGroupFromPath(
- User, CUsr::GetUserClass(User), MyPath)) == INVALID_HANDLE_VALUE)
- {
- LogMsg(LOGF_DEBUG,"chmod(%s) - GetUserClass(%d) failed.", Path, User);
- rval = -2;
- goto done;
- }
- if ((SecurityDsc = CFsysSecurity::GetSecurityDescriptor(SecurityGrp,fpath)) == INVALID_HANDLE_VALUE)
- {
- // Create a new security handle for this file
- if ((SecurityDsc = CFsysSecurity::CreateNode(User, SecurityGrp, IsDir, fpath)) == INVALID_HANDLE_VALUE)
- {
- LogMsg(LOGF_DEBUG,"chmod(%s) - faled to create new security handle.", Path);
- rval = -3;
- goto done;
- }
- }
- fsn = (CFsysSecurityNode *)SecurityDsc;
- ASSERT(AfxIsValidAddress(fsn, sizeof(CFsysSecurityNode)));
- if ((User && !CUsr::IsAdmin(User)) && (User != fsn->Owner))
- {
- LogMsg(LOGF_DEBUG,"chmod(%s) - Only root and owner can chmod. User = %d.", Path, User);
- rval = -4;
- goto done;
- }
- // Set the new permissions
- if (SetMode != -1)
- fsn->Perms = (SetMode & NODE_SETTABLE);
- if (SetOwner != -1)
- fsn->Owner = SetOwner;
- if (SetClass != -1)
- fsn->Class = SetClass;
- if (SetComment)
- fsn->Comment = SetComment;
- if (IsDir)
- fsn->Perms |= S_IFDIR;
- if ((dw != 0xFFFFFFFF) && (dw & FILE_ATTRIBUTE_READONLY))
- {
- fsn->Perms &= ~NODE_WRITEMSK;
- fsn->Perms |= NODE_READONLY;
- }
- // Save the new data.
- if (!CFsysSecurity::FlushGroup(SecurityGrp))
- rval = -1;
- done:
- CFsysSecurity::UnLock();
- if (SecurityGrp != INVALID_HANDLE_VALUE)
- CFsysSecurity::CloseSecurityGroup(SecurityGrp);
- free(MyPath);
- return rval;
- }
- ///////////////////////////////////////////////////////////////////////////
- // CFindFileHandle - support class for Find*File()
- CFindFileHandle::CFindFileHandle()
- {
- m_DOShandle = INVALID_HANDLE_VALUE;
- m_PathsQueued = NULL;
- m_User = 0;
- m_Pattern.Empty();
- m_Argc = 0;
- }
- CFindFileHandle::~CFindFileHandle()
- {
- if (m_PathsQueued)
- {
- ASSERT(AfxIsValidAddress(m_PathsQueued,sizeof(CCmdArgs)));
- delete m_PathsQueued;
- }
- ASSERT(m_DOShandle == INVALID_HANDLE_VALUE);
- // Delete the security group descriptor
- if (m_SecurityHandle != INVALID_HANDLE_VALUE)
- {
- CFsysSecurityGrp *pGrp = (CFsysSecurityGrp *)m_SecurityHandle;
- ASSERT(AfxIsValidAddress(pGrp,sizeof(CFsysSecurityGrp)));
- delete pGrp;
- }
- }