📄 fsdvol.c
字号:
#include "vxd.h"
#include "shared\vxddebug.h"
#include "error.h"
#include "fsdfile.h"
#include "fsdvol.h"
#include "ext2fs.h"
#include "super.h"
#include "inode.h"
#include "unixstat.h"
#include "util.h"
#include "dir.h"
#include "file.h"
#include "crs.h"
//extern PVRP gVrp;
#define SUPER(ioreq) ( ((TSuperBlock *) (ioreq)->ir_rh) )
//static int __cdecl FsdShortFindNext(pioreq Ioreq) {return 0;}
//static TFindContext* FsdPrepareFindNext(pioreq Ioreq) {return 0;}
//static ext2_dir_entry* FsdDoFindNext(TFindContext *findcontext, ext2_inode *Inode, char *ShortName) { return 0;}
//static int __cdecl FsdLfnFindNext(pioreq Ioreq) {return 0;}
/**********************************
*
* STATIC DATA
*
**********************************/
static hndlmisc sFsdFileFunctions =
{
IFS_VERSION,
IFS_REVISION,
NUM_HNDLMISC,
FsdFileSeek,
FsdFileClose,
FsdFileCommit,
FsdFileFilelocks,
FsdFileFiletimes,
FsdFilePiperequest,
FsdFileHandleInfo,
FsdFileEnumHandle
};
static hndlmisc gFsdFindFunctions =
{
IFS_VERSION,
IFS_REVISION,
NUM_HNDLMISC,
{
FsdFileEmptyFunc,
FsdFileFindClose,
FsdFileEmptyFunc,
FsdFileEmptyFunc,
FsdFileEmptyFunc,
FsdFileEmptyFunc,
FsdFileEmptyFunc,
FsdFileEnumHandle
}
};
static char gFileSystem[] = "ext2 fs";
static char gResourceName[] = "linux";
#ifdef DEBUG
static char* sDirActions[] =
{
"create",
"delete",
"check",
"query8.3",
"querylfn"
};
static char* sAttribActions[] =
{
"GET_ATTRIBUTES",
"SET_ATTRIBUTES",
"GET_ATTRIB_COMP_FILESIZE",
"SET_ATTRIB_MODIFY_DATETIME",
"GET_ATTRIB_MODIFY_DATETIME",
"SET_ATTRIB_LAST_ACCESS_DATETIME",
"GET_ATTRIB_LAST_ACCESS_DATETIME",
"SET_ATTRIB_CREATION_DATETIME",
"GET_ATTRIB_CREATION_DATETIME",
"GET_ATTRIB_FIRST_CLUST"
};
#endif
/**********************************
*
* STATIC HELPERS
*
**********************************/
#ifdef NYI
static PIOR CreateIOR(PVRP Vrp, DWORD opcode, DWORD flags, int Drive)
{
DWORD size = Vrp->VRP_max_req_size + Vrp->VRP_max_sgd * sizeof(SGD);
DWORD offset = Vrp->VRP_delta_to_ior;
PIOR ior = IspCreateIor((USHORT) size, (USHORT) offset, ISP_M_FL_MUST_SUCCEED);
if (!ior)
return NULL;
ior->IOR_next = 0; // used for request queueing by lots of downstream people
ior->IOR_start_addr[1] = 0; // assume only 32-bits worth of sector number
ior->IOR_flags = IORF_VERSION_002 | flags; // this is how IOS knows we're giving it a new-style IOR
ior->IOR_private_client = offset; // a common use for this field
ior->IOR_req_vol_handle = (ULONG) Vrp;
ior->IOR_sgd_lin_phys = (ULONG) (ior + 1); // where scatter/gather descriptors can be built
ior->IOR_num_sgds = 0; // incremented by criteria routine, so must start at zero
ior->IOR_vol_designtr = Drive; // drive number
ior->IOR_func = (USHORT) opcode;
return ior;
}
static void DestroyIOR(PIOR ior)
{
IspDeallocMem((PVOID) ((DWORD) ior - ior->IOR_private_client));
}
#endif /* NYI */
static void FillLfnFindData(TFindContext *FindContext, _WIN32_FIND_DATA *FindData)
{
_QWORD Result;
ext2_inode *ext2inode;
/*
* We've set the attributes when we tested them for a match
*/
ext2inode = InodeLock(FindContext->FoundInode);
FindData->dwFileAttributes = FindContext->FoundInode->DosAttrib;
IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_ctime), &FindData->ftCreationTime);
IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_atime), &FindData->ftLastAccessTime);
IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_mtime), &FindData->ftLastWriteTime);
FindData->nFileSizeHigh = 0;
FindData->nFileSizeLow = ext2inode->i_size;
/*
* Convert to Unicode LFN FileName
*/
BCSToUni(FindData->cFileName, FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, BCS_OEM, &Result);
FindData->cFileName[Result.ddLower >> 1] = 0;
/*
* Convert to Unicode Short FileName, make sure we do not
* convert . or ..
*/
if (isDotOrDotDot(FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len))
{
BCSToUni(FindData->cAlternateFileName, FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, BCS_OEM, &Result);
FindData->cAlternateFileName[Result.ddLower >> 1] = 0;
}
else
{
LongToShort(FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, FindContext->ShortName, FindContext->FoundDirEntry->inode);
BCSToUni(FindData->cAlternateFileName, FindContext->ShortName, strlen(FindContext->ShortName), BCS_OEM, &Result);
FindData->cAlternateFileName[Result.ddLower >> 1] = 0;
}
InodeUnlock(FindContext->FoundInode);
}
static void FillShortFindData(TFindContext *FindContext, srch_entry *SearchEntry)
{
dos_time d;
ext2_inode *ext2inode;
ext2inode = InodeLock(FindContext->FoundInode);
SearchEntry->se_attrib = (UCHAR) FindContext->FoundInode->DosAttrib;
d = dateUnix2Dos(ext2inode->i_mtime);
SearchEntry->se_time = d.dt_time;
SearchEntry->se_date = d.dt_date;
SearchEntry->se_size = ext2inode->i_size;
strcpy(SearchEntry->se_name, FindContext->ShortName);
InodeUnlock(FindContext->FoundInode);
}
/*
* Called by both FsdFindFirst and FsdSearch
* to setup search info
*
*/
static TFindContext* FsdPrepareFindNext(pioreq Ioreq)
{
TFindContext *findcontext;
TInode *inode;
char bcspathname[MAX_PATH];
char *filename;
char *path;
VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext");
findcontext = 0;
Ioreq->ir_error = 0;
/*
* First get the bcs_pathname of the directory in which
* the lookup is to be performed
*/
if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcspathname))
{
/*
* Cut off the file name part by looking for the
* last dirname separator
*/
if ((filename = strrchr(bcspathname, '/')))
{
path = bcspathname;
*filename++ = 0;
}
else
{
path = "";
filename = bcspathname; // we only have a filename
}
/*
* Get the inode belonging to the directoryname
*/
if ( (inode = DirName2Inode(SUPER(Ioreq), path)))
{
/*
*/
if ((findcontext = DirCreateFindContext(inode, filename, Ioreq->ir_attr)))
{
/*
* As we peform the matching ourselves, translate
* "*.*" in "*"
*/
if (findcontext->SearchFlags & FILE_FLAG_HAS_DOT)
{
findcontext->SearchFlags &= ~FILE_FLAG_HAS_DOT;
SmartConvertDots2QuestionMark(findcontext->SearchName);
}
}
else
{
Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
InodeRelease(inode);
}
}
else
{
VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext: path not found");
Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
}
}
else
{
VxdDebugPrint(D_ERROR, "FsdPrepareFindNext: could not getbcspath on:%U", Ioreq->ir_upath);
Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
}
VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext: done");
return findcontext;
}
static int __cdecl FsdLfnFindNext(pioreq Ioreq)
{
TFindContext *findcontext;
/*
* Search for entry, using lfn matching scheme
*/
Ioreq->ir_error = 0;
findcontext = (TFindContext *) Ioreq->ir_fh;
if (findcontext)
{
VxdDebugPrint(D_VOLUME, "FNEXT(lfn): inode=(dev=%s, ino=%lu), search=%s",
findcontext->Inode->Super->DeviceName,
findcontext->Inode->InodeNo,
findcontext->SearchName);
/*
* Perform a lookup on long names
*/
if ((DirFindEntry(findcontext, FALSE)))
{
/*
/*
* Great! found a match...
* Fill in the Win32 FindData structure
*/
FillLfnFindData(findcontext, Ioreq->ir_data);
BlockUnlock(findcontext->Block);
InodeRelease(findcontext->FoundInode);
VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done, found:%U",
((_WIN32_FIND_DATA *) Ioreq->ir_data)->cFileName);
}
else
{
VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done, no more files");
Ioreq->ir_error = ERROR_NO_MORE_FILES;
}
VxdDebugFlush();
}
else
{
VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done (no findcontext), no more files");
Ioreq->ir_error = ERROR_NO_MORE_FILES;
}
return Ioreq->ir_error;
}
static int __cdecl FsdShortFindNext(pioreq Ioreq)
{
TFindContext *findcontext;
srch_entry *search_entry;
/*
* Search for entry, using lfn matching scheme
*/
Ioreq->ir_error = 0;
search_entry = (srch_entry *) Ioreq->ir_data;
memcpy(&findcontext, search_entry->se_key.sk_localFSD, 4);
VxdDebugPrint(D_VOLUME, "FNEXT(short): inode=(dev=%s, ino=%lu), search=%s",
findcontext->Inode->Super->DeviceName,
findcontext->Inode->InodeNo,
findcontext->SearchName);
if ((DirFindEntry(findcontext, TRUE)))
{
/*
/*
* Great! found a match...
* Fill in the search entry structure
*/
FillShortFindData(findcontext, search_entry);
BlockUnlock(findcontext->Block);
InodeRelease(findcontext->FoundInode);
VxdDebugPrint(D_VOLUME, "FNEXT(short): done, found:%s",
findcontext->ShortName);
}
else
{
VxdDebugPrint(D_VOLUME, "FNEXT(short): done, no more files");
Ioreq->ir_error = ERROR_NO_MORE_FILES;
DirDestroyFindContext(findcontext);
}
VxdDebugFlush();
return Ioreq->ir_error;
#ifdef NYI
TFindContext *findcontext;
ext2_inode inode;
ext2_dir_entry *dir_entry;
srch_entry *search_entry;
/*
* Search for entry, using short filename matching scheme
*/
Ioreq->ir_error = 0;
search_entry = (srch_entry *) Ioreq->ir_data;
memcpy(&findcontext, search_entry->se_key.sk_localFSD, 4);
if ((dir_entry=FsdDoFindNext(findcontext, &inode, search_entry->se_name)))
{
/*
/*
* Great! found a match...
* Fill in the search entry structure
*/
FillShortFindData(dir_entry, &inode, search_entry);
}
else
Ioreq->ir_error = ERROR_NO_MORE_FILES;
return Ioreq->ir_error;
#endif /* NYI */
}
/**********************************
*
* INTERFACE ROUTINES
*
**********************************/
int __cdecl FsdVolOpen(pioreq Ioreq)
{
char bcsfilename[MAX_PATH];
TFileContext *filecontext;
TInode *inode;
ext2_inode *ext2inode;
unsigned char flags;
VxdDebugPrint(D_VOLUME, "FileOpen, file=%U, sfn=%lu, flags=%lu, options=%lu",
Ioreq->ir_upath, (ULONG) Ioreq->ir_sfn, (ULONG) Ioreq->ir_flags, (ULONG) Ioreq->ir_options);
if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcsfilename))
{
if ((inode = DirName2Inode(SUPER(Ioreq), bcsfilename)))
{
//if (!S_ISDIR(inode->Mode))
if (S_ISREG(inode->Mode))
{
/*
* We are a read-only file system
*/
flags = Ioreq->ir_flags & ACCESS_MODE_MASK;
if ( ((flags == ACCESS_READONLY) || (flags != ACCESS_EXECUTE))
&&
((Ioreq->ir_options == ACTION_OPENEXISTING) || (Ioreq->ir_options == ACTION_OPENALWAYS)))
{
if ((filecontext = FileCreateFileContext(inode)))
{
ext2inode = InodeLock(inode);
Ioreq->ir_hfunc->hf_read = FsdFileRead;
Ioreq->ir_hfunc->hf_write = FsdFileWrite;
Ioreq->ir_hfunc->hf_misc = &sFsdFileFunctions;
Ioreq->ir_fh = filecontext;
Ioreq->ir_options = ACTION_OPENED;
Ioreq->ir_size = filecontext->FileSize;
Ioreq->ir_attr = inode->DosAttrib;
Ioreq->ir_dostime = dateUnix2Dos(ext2inode->i_mtime);
Ioreq->ir_error = 0;
InodeUnlock(inode);
}
else
{
Ioreq->ir_error = ERROR_NOT_ENOUGH_MEMORY;
InodeRelease(inode);
}
}
else
{
Ioreq->ir_error = ERROR_ACCESS_DENIED;
InodeRelease(inode);
}
}
else
{
Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
InodeRelease(inode);
}
}
else
Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
}
else
Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
VxdDebugPrint(D_VOLUME, "FileOpen, done, error=%lu", Ioreq->ir_error);
VxdDebugFlush();
return Ioreq->ir_error;
}
int __cdecl FsdVolIoctl16(pioreq Ioreq)
{
CLIENT_STRUCT *pRegs;
PIOR ior;
USHORT status;
pRegs = (CLIENT_STRUCT*) Ioreq->ir_cregptr;
VxdDebugPrint(D_VOLUME, "IOCTL16, al=%x, bl=%x, cl=%x", (unsigned) _clientAL, (unsigned) _clientBL, (unsigned) _clientCL);
Ioreq->ir_error = 5;
VxdDebugFlush();
return Ioreq->ir_error;
#ifdef NYI
ior = CreateIOR((PVRP) SUPER(Ioreq)->Vrp, IOR_GEN_IOCTL, IORF_SYNC_COMMAND, SUPER(Ioreq)->DosDrive);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -