//
// $Header: D:/ext2-os2/RCS/fs_find.c,v 1.10 1995/08/16 17:37:15 Willm Exp Willm $
//
// Linux ext2 file system driver for OS/2 2.x and WARP - Allows OS/2 to
// access your Linux ext2fs partitions as normal drive letters.
// OS/2 implementation : Copyright (C) 1995 Matthieu WILLM
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h> // From the "Developer Connection Device Driver Kit" version 2.0
#include <fsd.h>
#include <fsh.h>
#include <linux/stat.h>
#include <os2/os2proto.h>
#include <os2/os2misc.h>
#include <os2/ifsdbg.h>
#include <os2/filefind.h>
#include <os2/cdfsd.h>
#include <os2/errors.h>
#include <os2/log.h> /* Prototypes des fonctions de log.c */
#include <os2/volume.h> /* Prototypes des fonctions de volume.c */
#include <os2/files.h> /* Prototypes des fonctions de files.c */
#include <linux/fs.h>
#include <linux/fs_proto.h>
#define THISFILE FILE_FS_FIND_C
#define FIL_LEVEL7 7 // Level 7, return case preserved path name
#define FILE_NONFAT 0x0040 // File is non 8.3 compliant
//
// date_dos2unix and date_unix2dos are from the Linux FAT file system
//
/* Linear day numbers of the respective 1sts in non-leap years. */
static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
// extern struct timezone sys_tz;
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
long date_dos2unix(unsigned short time,unsigned short date)
{
long month,year,secs;
month = ((date >> 5) & 15)-1;
year = date >> 9;
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
month < 2 ? 1 : 0)+3653);
/* days since 1.1.70 plus 80's leap day */
// secs += sys_tz.tz_minuteswest*60;
return secs;
}
/* Convert linear UNIX date to a MS-DOS time/date pair. */
void date_unix2dos(long unix_date,unsigned short _FS_PTR time,
unsigned short _FS_PTR date)
{
long day,year,nl_day,month;
// unix_date -= sys_tz.tz_minuteswest*60;
*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
(((unix_date/3600) % 24) << 11);
day = unix_date/86400-3652;
year = day/365;
if ((year+3)/4+365*year > day) year--;
day -= (year+3)/4+365*year;
if (day == 59 && !(year & 3)) {
nl_day = day;
month = 2;
}
else {
nl_day = (year & 3) || day <= 59 ? day : day-1;
for (month = 0; month < 12; month++)
if (day_n[month] > nl_day) break;
}
*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
}
/* 1 - means OK, 0 means doesn't match */
int filter_with_attrs(struct inode * pino, unsigned short attrs, pchar name) {
unsigned short mayhave = attrs & 0xFF;
unsigned short musthave = (attrs >> 8) & 0xFF;
unsigned short mapped;
mapped = Linux_To_DOS_Attrs(pino, name);
/*
Actual May have Must have Included a&may&must ~a&~may&~must a&may&~must ~a&may&~must
1 1 1 y 1 0 0 0
1 1 0 y 0 0 1 0
1 0 1 n 0 0 0 0
1 0 0 n 0 0 0 0
0 1 1 n 0 0 0 0
0 1 0 y 0 0 0 1
0 0 1 n 0 0 0 0
0 0 0 y 0 1 0 0
=> a & may | ~a & ~must
*/
return !(~(( (mapped & mayhave) | ( (~mapped) & (~musthave)))));
}
#define TYPEOP_FILEFIND 1
#define TYPEOP_FILEINFO 2
int ino_to_fileinfo(
struct inode * pino,
pchar databuf,
UINT32 maxlen,
PUINT32 plen,
unsigned short level,
unsigned short flags,
unsigned short attrs,
struct dirent *pDir,
INT32 position, int TypeOp) {
pCommonFileInfo pCommon;
pFileName pFile;
PINT32 pPosition;
*plen = 0;
/***************************************************************************/
/*** First field : long position if FF_GETPOS - nothing if FF_NOPOS ***/
/***************************************************************************/
if (TypeOp == TYPEOP_FILEFIND) {
if (flags == FF_GETPOS) {
if (sizeof(INT32) + *plen > maxlen) {
fs_log("ino_to_fileinfo() - Buffer overflow for first field");
return ERROR_BUFFER_OVERFLOW;
}
pPosition = (PINT32)(databuf + *plen);
*pPosition = position;
*plen += sizeof(INT32);
}
}
/***************************************************************************/
/***************************************************************************/
/*** Second field : common file information to all level/flags ***/
/***************************************************************************/
if (sizeof(CommonFileInfo) + *plen > maxlen) {
kernel_printf("ino_to_fileinfo() - Buffer overflow for second field - len = %lu - maxlen = %lu", (UINT32)sizeof(CommonFileInfo) + (UINT32)(*plen), (UINT32)maxlen);
return ERROR_BUFFER_OVERFLOW;
}
pCommon = (pCommonFileInfo)(databuf + *plen);
date_unix2dos(pino->i_ctime, &(pCommon->timeCreate), &(pCommon->dateCreate));
date_unix2dos(pino->i_atime, &(pCommon->timeAccess), &(pCommon->dateAccess));
date_unix2dos(pino->i_ctime, &(pCommon->timeWrite), &(pCommon->dateWrite));
pCommon->cbEOF = pino->i_size;
pCommon->cbAlloc = pino->i_blocks;
pCommon->attr = FILE_NORMAL;
if ((S_ISLNK(pino->i_mode)) ||
(S_ISBLK(pino->i_mode)) ||
(S_ISCHR(pino->i_mode)) ||
(S_ISFIFO(pino->i_mode)) ||
(S_ISSOCK(pino->i_mode))) {
pCommon->attr |= FILE_SYSTEM; /*** UNIXish special files are seen as SYSTEM files ***/
} /* endif */
if (S_ISDIR(pino->i_mode)) {
pCommon->attr |= FILE_DIRECTORY;
} /* endif */
if ((!(pino->i_mode & S_IWUSR)) &&
(!(pino->i_mode & S_IWGRP)) &&
(!(pino->i_mode & S_IWOTH))) {
pCommon->attr |= FILE_READONLY;
}
*plen += sizeof(CommonFileInfo);
/***************************************************************************/
/***************************************************************************/
/*** Third field : nothing for level FIL_STANDARD ***/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/*** Third field : Size on disk of EA set for FIL_QUERYEASIZE ***/
/***************************************************************************/
if (level == FIL_QUERYEASIZE) {
if (sizeof(INT32) + *plen > maxlen) {
fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASIZE");
return ERROR_BUFFER_OVERFLOW;
}
*((PINT32)(databuf + *plen)) = 0; /*** No EAS in ext2 ***/
*plen += sizeof(INT32);
}
/***************************************************************************/
/***************************************************************************/
/*** Third field : FEAList for level QUERYEASFROMLIST ***/
/***************************************************************************/
if (level == FIL_QUERYEASFROMLIST) {
if (sizeof(INT32) + *plen > maxlen) {
fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASFROMLIST");
return ERROR_BUFFER_OVERFLOW;
}
*((PINT32)(databuf + *plen)) = 4; /*** No EAS in ext2 ***/ /* this is the length field of FEAList */
*plen += sizeof(INT32);
}
/***************************************************************************/
/***************************************************************************/
/*** Fourth field : name ***/
/***************************************************************************/
if (TypeOp == TYPEOP_FILEFIND) {
if (*plen + sizeof(FileName) + pDir->d_reclen > maxlen) {
fs_log("ino_to_fileinfo() - Buffer overflow for fourth field");
return ERROR_BUFFER_OVERFLOW;
}
pFile = (pFileName)(databuf + *plen);
pFile->cbName = (unsigned char)pDir->d_reclen; /* name length WITHOUT '\0' */
strcpy(pFile->szName, pDir->d_name); /* name WITH '\0' */
*plen += sizeof(FileName) + pDir->d_reclen; /* sizeof(FileName) + strlen(Dir.d_name) */
}
/***************************************************************************/
return NO_ERROR;
}
int myfindnext(
struct super_block * p_volume,
pfile p_file,
unsigned short attr,
struct fsfsi _FS_PTR pfsfsi,
struct fsfsd _FS_PTR pfsfsd,
pchar pData,
unsigned short cbData,
unsigned short _FS_PTR pcMatch,
unsigned short level,
unsigned short flags,
UINT32 index_dir,
int is_findfirst,
id_t *pmyid
) {
UINT32 cur_size;
int rc;
struct dirent Dir;
pchar pNom;
pchar pWork, pWorkUpper;
pchar pName, pNameUpper;
UINT32 len;
struct inode * ino;
UINT16 nb_found;
pName = ((p_hfind)pfsfsd)->pName;
pNom = pName + CCHMAXPATH;
pWork = pName + 2 * CCHMAXPATH;
pNameUpper = pName + 3 * CCHMAXPATH;
pWorkUpper = pName + 4 * CCHMAXPATH;
nb_found = 0;
if (level == FIL_QUERYEASFROMLIST) {
cur_size = sizeof(EAOP);
} else {
cur_size = 0;
}
while (nb_found < *pcMatch) {
/***********************************************************/
/*** If we are at the end of the parent dir : stop ***/
/***********************************************************/
if (VFS_readdir(p_file, &Dir) != NO_ERROR) {
((p_hfind)pfsfsd)->last = index_dir;
*pcMatch = nb_found;
if (nb_found > 0) {
#ifdef FS_TRACE
kernel_printf("myfindnext() - EOD - found %d entries", nb_found);
#endif
return NO_ERROR;
} else {
#if 1
if (is_findfirst) {
/************************************************************************/
/*** Libération du buffer stockant les noms de recherche ***/
/************************************************************************/
if ((rc = G_free(((p_hfind)pfsfsd)->pName)) != NO_ERROR) {
fs_err(FUNC_FS_FINDFIRST, FUNC_G_free, rc, THISFILE, __LINE__);
return rc;
} /* end if */
/************************************************************************/
if ((rc = _close(p_volume, &p_file)) != NO_ERROR) {
fs_err(FUNC_FS_FINDFIRST, FUNC_CLOSE, rc, THISFILE, __LINE__);
return rc;
}
// ((p_hfind)pfsfsd)->FS_CLOSEd = SEARCH_ALREADY_CLOSED;
}
#else
FS_FINDCLOSE(pfsfsi, pfsfsd);
((p_hfind)pfsfsd)->FS_CLOSEd = SEARCH_ALREADY_CLOSED;
#endif
return ERROR_NO_MORE_FILES;
}
} /* end if */
/***********************************************************/
/***********************************************************/
/*** If we found an entry, see if it matches ***/
/***********************************************************/
strcpy(pWork, pNom);
strcat(pWork, "\\");
if (pmyid->pdb != 0) {
FSH_UPPERCASE(Dir.d_name, strlen(Dir.d_name) + 1, Dir.d_name);
}
strcat(pWork, Dir.d_name);
#if 0
#if 1
if (pmyid->pdb != 0) {
FSH_UPPERCASE(pName, CCHMAXPATH, pNameUpper);
FSH_UPPERCASE(pWork, CCHMAXPATH, pWorkUpper);
} else {
strcpy(pNameUpper, pName);
strcpy(pWorkUpper, pWork);
}
if (FSH_WILDMATCH(pNameUpper, pWorkUpper) == NO_ERROR) {
#else
if (FSH_WILDMATCH(pName, pWork) == NO_ERROR) {
#endif
#else
if (FSH_WILDMATCH(pName, pWork) == NO_ERROR) {
#endif
if (p_file->f_inode->i_ino != Dir.d_ino) {
if ((ino = iget(p_volume, Dir.d_ino)) == NULL) {
fs_err(FUNC_FS_FINDFIRST, FUNC_GET_VINODE, rc, THISFILE, __LINE__);
return ERROR_NO_MORE_FILES;
} /* endif */
} else {
ino = p_file->f_inode;
}
if (filter_with_attrs(ino, attr | FILE_READONLY, Dir.d_name)) {
if ((rc = ino_to_fileinfo(
ino,
pData + cur_size,
cbData - cur_size,
&len,
level,
flags,
attr,
&Dir,
index_dir, TYPEOP_FILEFIND)) != NO_ERROR) {
*pcMatch = nb_found;
((p_hfind)pfsfsd)->last = index_dir;
fs_log("====> FS_FINDFIRST : erreur ino_to_fileinfo()");
if (p_file->f_inode->i_ino != Dir.d_ino) {
iput(ino);
}
return rc;
}
nb_found ++;
cur_size += len;
}
if (p_file->f_inode->i_ino != Dir.d_ino) {
iput(ino);
}
} /* end if */
/***********************************************************/
index_dir ++;
} /* end while */
*pcMatch = nb_found;
((p_hfind)pfsfsd)->last = index_dir;
#ifdef FS_TRACE
kernel_printf("myfindnext() - found %d entries", nb_found);
#endif
return NO_ERROR;
}
/*************************************************************************************************/
/*** FS_FINDFIRST - IFS find first matching file(s) entry point (DosFindFirst API) ***/
/*************************************************************************************************/
int _FS_ENTRY FS_FINDFIRST(
struct cdfsi _FS_PTR pcdfsi,
struct cdfsd _FS_PTR pcdfsd,
char _FS_PTR pName,
unsigned short iCurDirEnd,
unsigned short attr,
struct fsfsi _FS_PTR pfsfsi,
struct fsfsd _FS_PTR pfsfsd,
char _FS_PTR pData,
unsigned short cbData,
unsigned short _FS_PTR pcMatch,
unsigned short level,
unsigned short flags
)
{
int rc;
UINT32 openmode = 0;
pchar pNom;
pfile p_file;
struct super_block * p_volume;
id_t myid;
#ifdef FS_TRACE
kernel_printf("FS_FINDFIRST( %s , match = %u , level = %u, flag = %u)", pName, *pcMatch, level, flags);
#endif
/*******************************************************************/
/*** Verify we have write access to the user buffer ***/
/*******************************************************************/
if ((rc = FSH_PROBEBUF(PB_OPWRITE, pData, cbData)) != NO_ERROR) {
fs_err(FUNC_FS_FINDFIRST, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
/*******************************************************************/
if ((flags != FF_NOPOS) &&
(flags != FF_GETPOS)) {
if ((rc = fs_log("FS_FINDFIRST() - invalid flag")) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
if ((level != FIL_STANDARD) &&
(level != FIL_QUERYEASIZE) &&
(level != FIL_QUERYEASFROMLIST)) {
if ((rc = fs_log("FS_FINDFIRST() - invalid level")) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
/*******************************************************************/
/*** Process identification (to recognize DOS box requests) ***/
/*******************************************************************/
if ((rc = FSH_QSYSINFO(2, (pchar)&myid, sizeof(id_t))) != NO_ERROR) {
fs_log("erreur FSH_QSYSINFO() dans FS_FINDFIRST");
return rc;
}
if (myid.pdb != 0) { // DOS Box request => uppercase
openmode |= OPENMODE_DOSBOX;
}
/*******************************************************************/
//
// Gets the superblock
//
p_volume = getvolume(pfsfsi->fsi_hVPB);
//
// Verify the user asked something !
//
if (*pcMatch == 0) {
fs_log("FS_FINDFIRST - *pcMatch = 0");
return ERROR_INVALID_PARAMETER;
} /* end if */
//
// Saves the file name to search into pfsfd
//
if ((((p_hfind)pfsfsd)->pName = G_malloc(5 * CCHMAXPATH)) == 0) {
fs_err(FUNC_FS_FINDFIRST, FUNC_G_free, ERROR_NOT_ENOUGH_MEMORY, THISFILE, __LINE__);
return ERROR_NOT_ENOUGH_MEMORY;
} /* end if */
strcpy(((p_hfind)pfsfsd)->pName, pName);
pNom = ((p_hfind)pfsfsd)->pName + CCHMAXPATH;
((p_hfind)pfsfsd)->attr = attr | FILE_READONLY; /* cf doc : may have Readonly bit never passed */
//
// Extracts the parent directory name
//
ExtractPath(pName, pNom);
//
// Opens the parent directory
//
if ((p_file = _open_by_name(p_volume, pNom, openmode | OPENMODE_READONLY)) == 0) {
fs_err(FUNC_FS_FINDFIRST, FUNC_OPEN_BY_NAME, ERROR_PATH_NOT_FOUND, THISFILE, __LINE__);
G_free(((p_hfind)pfsfsd)->pName);
return ERROR_PATH_NOT_FOUND;
} /* end if */
((p_hfind)pfsfsd)->p_file = p_file;
// ((p_hfind)pfsfsd)->FS_CLOSEd = SEARCH_NOT_CLOSED;
//
// Do the actual search
//
rc = myfindnext(
p_volume,
p_file,
attr | FILE_READONLY,
pfsfsi,
pfsfsd,
pData,
cbData,
pcMatch,
level,
flags,
0,
1,
&myid
);
#ifdef FS_TRACE
kernel_printf("FS_FINDFIRST - myfindnext returned %d - pcMatch = %d", rc, *pcMatch);
#endif
return rc;
}
/*************************************************************************************************/
/*************************************************************************************************/
/*** FS_FINDCLOSE - IFS close file search entry point (DosFindClose API) ***/
/*************************************************************************************************/
int _FS_ENTRY FS_FINDCLOSE(
struct fsfsi _FS_PTR pfsfsi,
struct fsfsd _FS_PTR pfsfsd
)
{
int rc;
struct super_block * p_volume;
#ifdef FS_TRACE
kernel_printf("FS_FINDCLOSE( %s )", ((p_hfind)pfsfsd)->pName);
#endif
//
// Gets the superblock from pfsfsi
//
p_volume = getvolume(pfsfsi->fsi_hVPB);
//
// Frees the memory allocated for the search
//
if ((rc = G_free(((p_hfind)pfsfsd)->pName)) != NO_ERROR) {
fs_err(FUNC_FS_FINDCLOSE, FUNC_G_free, rc, FILE_FS_FIND_C, __LINE__);
return rc;
} /* end if */
//
// Closes the search directory
//
if ((rc = _close(p_volume, &(((p_hfind)pfsfsd)->p_file))) != NO_ERROR) {
fs_err(FUNC_FS_FINDCLOSE, FUNC_CLOSE, rc, FILE_FS_FIND_C, __LINE__);
return rc;
}
return NO_ERROR;
}
/*************************************************************************************************/
/*************************************************************************************************/
/*** FS_FINDFROMNAME - IFS find next matching file(s) entry point (resume by name) ***/
/*************************************************************************************************/
_FS_RET _FS_ENTRY FS_FINDFROMNAME(
struct fsfsi _FS_PTR pfsfsi,
struct fsfsd _FS_PTR pfsfsd,
char _FS_PTR pData,
unsigned short cbData,
unsigned short _FS_PTR pcMatch,
unsigned short level,
unsigned long position,
char _FS_PTR pNameFrom,
unsigned short flags
)
{
int rc;
struct super_block * p_volume;
id_t myid;
#ifdef FS_TRACE
kernel_printf("FS_FINDFROMNAME( %s , match = %u , level = %u, flag = %u)", ((p_hfind)pfsfsd)->pName, *pcMatch, level, flags);
#endif
//
// Verify we have write access to the user buffer
//
if ((rc = FSH_PROBEBUF(PB_OPWRITE, pData, cbData)) != NO_ERROR) {
fs_err(FUNC_FS_FINDFROMNAME, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
if ((flags != FF_NOPOS) &&
(flags != FF_GETPOS)) {
if ((rc = kernel_printf("FS_FINDFROMNAME() - invalid flags : %u", flags)) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
if ((level != FIL_STANDARD) &&
(level != FIL_QUERYEASIZE) &&
(level != FIL_QUERYEASFROMLIST)) {
if ((rc = kernel_printf("FS_FINDFROMNAME() - invalid level : %u", level)) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
/*******************************************************************/
/*** Process identification (to recognize DOS box requests) ***/
/*******************************************************************/
if ((rc = FSH_QSYSINFO(2, (pchar)&myid, sizeof(id_t))) != NO_ERROR) {
fs_log("erreur FSH_QSYSINFO() dans FS_FINDFIRST");
return rc;
}
//
// Gets the superblock from pfsfsi
//
p_volume = getvolume(pfsfsi->fsi_hVPB);
//
// Verifies the user asked something !
//
if (*pcMatch == 0) {
fs_log("FS_FINDFROMNAME - *pcMatch = 0");
return ERROR_INVALID_PARAMETER;
} /* end if */
//
// Do the actual search
//
return myfindnext(
p_volume,
((p_hfind)pfsfsd)->p_file,
((p_hfind)pfsfsd)->attr,
pfsfsi,
pfsfsd,
pData,
cbData,
pcMatch,
level,
flags,
((p_hfind)pfsfsd)->last,
0,
&myid
);
}
/*************************************************************************************************/
/*** FS_FINDNEXT - IFS find next matching file(s) entry point (resume by index) ***/
/*************************************************************************************************/
int _FS_ENTRY FS_FINDNEXT(
struct fsfsi _FS_PTR pfsfsi,
struct fsfsd _FS_PTR pfsfsd,
char _FS_PTR pData,
unsigned short cbData,
unsigned short _FS_PTR pcMatch,
unsigned short level,
unsigned short flags
)
{
int rc;
struct super_block * p_volume;
id_t myid;
#ifdef FS_TRACE
kernel_printf("FS_FINDNEXT( %s , match = %u , level = %u, flag = %u)", ((p_hfind)pfsfsd)->pName, *pcMatch, level, flags);
#endif
//
// Verifies we have write access to the user buffer
//
if ((rc = FSH_PROBEBUF(PB_OPWRITE, pData, cbData)) != NO_ERROR) {
fs_err(FUNC_FS_FINDNEXT, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
if ((flags != FF_NOPOS) &&
(flags != FF_GETPOS)) {
if ((rc = fs_log("FS_FINDNEXT() - invalid flag")) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
if ((level != FIL_STANDARD) &&
(level != FIL_QUERYEASIZE) &&
(level != FIL_QUERYEASFROMLIST)) {
if ((rc = fs_log("FS_FINDNEXT() - invalid level")) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
/*******************************************************************/
/*** Process identification (to recognize DOS box requests) ***/
/*******************************************************************/
if ((rc = FSH_QSYSINFO(2, (pchar)&myid, sizeof(id_t))) != NO_ERROR) {
fs_log("erreur FSH_QSYSINFO() dans FS_FINDFIRST");
return rc;
}
//
// Gets the superblock from pfsfsi
//
p_volume = getvolume(pfsfsi->fsi_hVPB);
//
// Verifies the user asked something !
//
if (*pcMatch == 0) {
fs_log("FS_FINDNEXT - *pcMatch = 0");
return ERROR_INVALID_PARAMETER;
} /* end if */
//
// Do the actual search
//
return myfindnext(
p_volume,
((p_hfind)pfsfsd)->p_file,
((p_hfind)pfsfsd)->attr,
pfsfsi,
pfsfsd,
pData,
cbData,
pcMatch,
level,
flags,
((p_hfind)pfsfsd)->last,
0,
&myid
);
}
/*************************************************************************************************/
_FS_RET _FS_ENTRY FS_FILEINFO(
unsigned short flag,
struct sffsi _FS_PTR psffsi,
struct sffsd _FS_PTR psffsd,
unsigned short level,
char _FS_PTR pData,
unsigned short cbData,
unsigned short IOflag
)
{
int rc;
UINT32 len;
pfile p_file;
struct super_block * p_volume;
PEAOP peaop;
if ((level != FIL_STANDARD) &&
(level != FIL_QUERYEASIZE) &&
(level != FIL_QUERYEASFROMLIST) &&
(level != FIL_QUERYALLEAS) && // Undocumented level - similar to level 3 but for full EA set
(level != FIL_LEVEL7)) {
if ((rc = kernel_printf("FS_FILEINFO() - invalid level %u", level)) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
}
//
// Get the superblock from psffsi
//
p_volume = getvolume(psffsi->sfi_hVPB);
//
// Gets the file structure from psffsd
//
p_file = ((_sffsd _FS_PTR)psffsd)->p_file;
switch(flag) {
case FI_SET :
#ifdef FS_TRACE
kernel_printf("FS_FILEINFO( FI_SET )");
#endif
if (Read_Write) {
// We should do something here !
return NO_ERROR;
} else {
return ERROR_WRITE_PROTECT;
}
case FI_RETRIEVE :
#ifdef FS_TRACE
if ((rc = kernel_printf("FS_FILEINFO(FI_RETRIEVE - lvl = %u - inode %lu )", level, p_file->f_inode->i_ino)) != NO_ERROR) {
return rc;
} /* end if */
#endif
//
// Verify we have write access to the user buffer
//
if ((rc = FSH_PROBEBUF(PB_OPWRITE, pData, cbData)) != NO_ERROR) {
fs_err(FUNC_FS_FILEINFO, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
if ((level == FIL_QUERYEASFROMLIST) ||
(level == FIL_QUERYALLEAS)) {
peaop = (PEAOP)pData;
if ((rc = FSH_PROBEBUF(PB_OPWRITE, (pchar)peaop, 4)) != NO_ERROR) {
fs_err(FUNC_FS_FILEINFO, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
peaop->fpFEAList->cbList = 4;
} else {
if ((rc = ino_to_fileinfo(
p_file->f_inode,
pData,
cbData,
&len,
level,
0,
0,
0,
0, TYPEOP_FILEINFO)) != NO_ERROR) {
fs_log("FS_FILEINFO() - ino_to_fileinfo()");
return rc;
}
}
break;
default :
fs_log("FS_FILEINFO() - Unknown flag");
return ERROR_INVALID_PARAMETER;
}
return NO_ERROR;
}
_FS_RET _FS_ENTRY FS_PATHINFO(
unsigned short flag,
struct cdfsi _FS_PTR pcdfsi,
struct cdfsd _FS_PTR pcdfsd,
char _FS_PTR pName,
unsigned short iCurDirEnd,
unsigned short level,
char _FS_PTR pData,
unsigned short cbData
)
{
int rc, rc3;
struct super_block * p_volume;
pfile p_file;
UINT32 len, openmode = 0;
PEAOP peaop;
id_t myid;
//
// Verify the level is valid
//
if ((level != FIL_STANDARD) &&
(level != FIL_QUERYEASIZE) &&
(level != FIL_QUERYEASFROMLIST) &&
(level != FIL_QUERYALLEAS) && // Undocumented level - similar to level 3 but for full EA set
(level != FIL_LEVEL7)) {
kernel_printf("FS_PATHINFO() - invalid level %u", level);
return ERROR_INVALID_PARAMETER;
}
/*******************************************************************/
/*** Process identification (to recognize DOS box requests) ***/
/*******************************************************************/
if ((rc = FSH_QSYSINFO(2, (pchar)&myid, sizeof(id_t))) != NO_ERROR) {
fs_log("erreur FSH_QSYSINFO() dans FS_FINDFIRST");
return rc;
}
if (myid.pdb != 0) {
openmode = OPENMODE_DOSBOX;
}
//
// Retrieves the superblock from psffsi
//
p_volume = getvolume(pcdfsi->cdi_hVPB);
switch(flag) {
case PI_RETRIEVE :
#ifdef FS_TRACE
if ((rc = kernel_printf("FS_PATHINFO(PI_RETRIEVE - lvl = %u - %s )", level, pName)) != NO_ERROR) {
return rc;
} /* end if */
#endif
//
// Verify we have write access to the user buffer
//
if ((rc = FSH_PROBEBUF(PB_OPWRITE, pData, cbData)) != NO_ERROR) {
fs_err(FUNC_FS_PATHINFO, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
switch(level) {
case FIL_LEVEL7 :
if (strlen(pName) + 1 > cbData) {
return ERROR_BUFFER_OVERFLOW;
}
memcpy(pData, pName,strlen(pName) + 1);
return NO_ERROR;
default :
if ((p_file = _open_by_name(p_volume, pName, openmode | OPENMODE_READONLY)) == 0) {
#ifdef FS_TRACE
fs_err(FUNC_FS_PATHINFO, FUNC_OPEN_BY_NAME, ERROR_PATH_NOT_FOUND, THISFILE, __LINE__);
#endif
return ERROR_FILE_NOT_FOUND;
}
if ((level == FIL_QUERYEASFROMLIST) ||
(level == FIL_QUERYALLEAS)) {
peaop = (PEAOP)pData;
if ((rc = FSH_PROBEBUF(PB_OPWRITE, (pchar)peaop, 4)) != NO_ERROR) {
fs_err(FUNC_FS_PATHINFO, FUNC_FSH_PROBEBUF, rc, THISFILE, __LINE__);
return rc;
} /* end if */
peaop->fpFEAList->cbList = 4; // NO EAS for ext2
} else {
if ((rc = ino_to_fileinfo(
p_file->f_inode,
pData,
cbData,
&len,
level,
0,
0,
0,
0, TYPEOP_FILEINFO)) != NO_ERROR) {
fs_log("FS_PATHINFO() - ino_to_fileinfo()");
if ((rc3 = _close(p_volume, &p_file)) != NO_ERROR) {
fs_err(FUNC_FS_PATHINFO, FUNC_CLOSE, rc3, THISFILE, __LINE__);
}
return rc;
}
}
if ((rc = _close(p_volume, &p_file)) != NO_ERROR) {
fs_err(FUNC_FS_PATHINFO, FUNC_CLOSE, rc, THISFILE, __LINE__);
return rc;
}
return NO_ERROR;
}
break;
case PI_SET :
case PI_SET + 0x10 :
#ifdef FS_TRACE
if ((rc = kernel_printf("FS_PATHINFO(PI_SET - %s )", pName)) != NO_ERROR) {
return rc;
} /* end if */
#endif
if (Read_Write) {
// We should do something here !
return NO_ERROR;
} else {
return ERROR_WRITE_PROTECT;
}
default :
if ((rc = kernel_printf("FS_PATHINFO( %s ) - unknown flag %d", pName, flag)) != NO_ERROR) {
return rc;
} /* end if */
return ERROR_INVALID_PARAMETER;
} /* end switch */
}