@@ -272,23 +272,29 @@ int XFile_GetStats(xfile_t *pFile)
272272 return pFile -> nSize ? XSTDOK : XSTDNON ;
273273}
274274
275- uint8_t * XFile_Load (xfile_t * pFile , size_t * pSize )
275+ uint8_t * XFile_LoadSize (xfile_t * pFile , size_t nMaxSize , size_t * pSize )
276276{
277277 if (pSize ) * pSize = 0 ;
278278 if (XFile_GetStats (pFile ) <= 0 || !S_ISREG (pFile -> nMode )) return NULL ;
279279
280- uint8_t * pBuffer = (uint8_t * )malloc (pFile -> nSize + 1 );
280+ size_t nAllowedToRead = XSTD_MIN (nMaxSize , pFile -> nSize );
281+ nAllowedToRead = nAllowedToRead ? nAllowedToRead : pFile -> nSize ;
282+
283+ uint8_t * pBuffer = (uint8_t * )malloc (nAllowedToRead + 1 );
281284 if (pBuffer == NULL ) return NULL ;
282285
283286 size_t nOffset = 0 ;
284287 int nBytes = 0 ;
285288
286289 do
287290 {
288- size_t nFreeSpace = pFile -> nSize - nOffset ;
291+ size_t nFreeSpace = nAllowedToRead - nOffset ;
289292 size_t nReadSize = pFile -> nBlockSize < nFreeSpace ?
290293 pFile -> nBlockSize : nFreeSpace ;
291294
295+ nReadSize = nReadSize < nMaxSize ? nReadSize : nMaxSize ;
296+ if (nReadSize == 0 ) break ;
297+
292298 nBytes = XFile_Read (pFile , & pBuffer [nOffset ], nReadSize );
293299 if (nBytes > 0 ) nOffset += nBytes ;
294300
@@ -306,6 +312,12 @@ uint8_t* XFile_Load(xfile_t *pFile, size_t *pSize)
306312 return pBuffer ;
307313}
308314
315+ uint8_t * XFile_Load (xfile_t * pFile , size_t * pSize )
316+ {
317+ // Use XSTDNON as MaxSize to read all file
318+ return XFile_LoadSize (pFile , XSTDNON , pSize );
319+ }
320+
309321int XFile_Copy (xfile_t * pIn , xfile_t * pOut )
310322{
311323 XASSERT ((XFile_GetStats (pIn ) > 0 ), XSTDERR );
@@ -668,6 +680,18 @@ uint8_t* XPath_Load(const char *pPath, size_t* pSize)
668680 return pData ;
669681}
670682
683+ uint8_t * XPath_LoadSize (const char * pPath , size_t nMaxSize , size_t * pSize )
684+ {
685+ if (pSize ) * pSize = 0 ;
686+ xfile_t file ;
687+
688+ if (XFile_Open (& file , pPath , NULL , NULL ) < 0 ) return NULL ;
689+ uint8_t * pData = XFile_LoadSize (& file , nMaxSize , pSize );
690+
691+ XFile_Close (& file );
692+ return pData ;
693+ }
694+
671695size_t XPath_LoadBuffer (const char * pPath , xbyte_buffer_t * pBuffer )
672696{
673697 if (pPath == NULL || pBuffer == NULL ) return 0 ;
@@ -685,6 +709,23 @@ size_t XPath_LoadBuffer(const char *pPath, xbyte_buffer_t *pBuffer)
685709 return nSize ;
686710}
687711
712+ size_t XPath_LoadBufferSize (const char * pPath , xbyte_buffer_t * pBuffer , size_t nMaxSize )
713+ {
714+ if (pPath == NULL || pBuffer == NULL ) return 0 ;
715+ XByteBuffer_Init (pBuffer , XSTDNON , XFALSE );
716+ size_t nSize = 0 ;
717+
718+ uint8_t * pData = XPath_LoadSize (pPath , nMaxSize , & nSize );
719+ if (pData != NULL )
720+ {
721+ pBuffer -> nSize = nSize + 1 ;
722+ pBuffer -> nUsed = nSize ;
723+ pBuffer -> pData = pData ;
724+ }
725+
726+ return nSize ;
727+ }
728+
688729int XPath_Write (const char * pPath , const char * pFlags , const uint8_t * pData , size_t nSize )
689730{
690731 if (pPath == NULL || pData == NULL || !nSize ) return XSTDERR ;
@@ -908,9 +949,11 @@ void XFile_InitEntry(xfile_entry_t *pEntry)
908949 pEntry -> sPath [0 ] = XSTR_NUL ;
909950 pEntry -> sName [0 ] = XSTR_NUL ;
910951 pEntry -> sLink [0 ] = XSTR_NUL ;
952+ pEntry -> sLine [0 ] = XSTR_NUL ;
911953 pEntry -> eType = XF_UNKNOWN ;
912954 pEntry -> pRealPath = NULL ;
913955 pEntry -> nLinkCount = 0 ;
956+ pEntry -> nLineNum = 0 ;
914957 pEntry -> nTime = 0 ;
915958 pEntry -> nSize = 0 ;
916959 pEntry -> nGID = 0 ;
@@ -1081,22 +1124,23 @@ static xbool_t XFile_SearchName(xfile_search_t *pSearch, const char *pFileName)
10811124 return bFound ;
10821125}
10831126
1084- static xbool_t XFile_CheckCriteria (xfile_search_t * pSearch , const char * pPath , const char * pName , xstat_t * pStat )
1127+ static int XFile_CheckCriteria (xfile_search_t * pSearch , const char * pPath , const char * pName , xstat_t * pStat )
10851128{
1086- if (pSearch -> nLinkCount >= 0 && pSearch -> nLinkCount != pStat -> st_nlink ) return XFALSE ;
1087- if (pSearch -> nFileSize >= 0 && pSearch -> nFileSize != pStat -> st_size ) return XFALSE ;
1129+ if (pSearch -> nLinkCount >= 0 && pSearch -> nLinkCount != pStat -> st_nlink ) return XSTDNON ;
1130+ if (pSearch -> nFileSize >= 0 && pSearch -> nFileSize != pStat -> st_size ) return XSTDNON ;
1131+ if (pSearch -> nMaxSize > 0 && pSearch -> nMaxSize < pStat -> st_size ) return XSTDNON ;
10881132
10891133 if (pSearch -> nPermissions )
10901134 {
10911135 char buff [XPERM_MAX ];
10921136 XPath_ModeToChmod (buff , sizeof (buff ), pStat -> st_mode );
1093- if (atoi (buff ) != pSearch -> nPermissions ) return XFALSE ;
1137+ if (atoi (buff ) != pSearch -> nPermissions ) return XSTDNON ;
10941138 }
10951139
10961140 if (pSearch -> nFileTypes )
10971141 {
10981142 xfile_type_t eType = XFile_GetType (pStat -> st_mode );
1099- if (!XFILE_CHECK_FL (pSearch -> nFileTypes , eType )) return XFALSE ;
1143+ if (!XFILE_CHECK_FL (pSearch -> nFileTypes , eType )) return XSTDNON ;
11001144 }
11011145
11021146 if (xstrused (pSearch -> pFileName ))
@@ -1109,30 +1153,69 @@ static xbool_t XFile_CheckCriteria(xfile_search_t *pSearch, const char *pPath, c
11091153 XFile_SearchName (pSearch , pSearchName ) :
11101154 !strcmp (pSearch -> pFileName , pSearchName );
11111155
1112- if (!bFound ) return XFALSE ;
1156+ if (!bFound && ! xstrused ( pSearch -> sText )) return XSTDNON ;
11131157 }
11141158
11151159 if (xstrused (pSearch -> sText ))
11161160 {
11171161 xfile_type_t eType = XFile_GetType (pStat -> st_mode );
1118- if (eType != XF_REGULAR ) return XFALSE ;
1162+ if (eType != XF_REGULAR ) return XSTDNON ;
11191163
11201164 char sPath [XPATH_MAX ];
11211165 xstrncpyf (sPath , sizeof (sPath ), "%s%s" , pPath , pName );
11221166
11231167 xbyte_buffer_t buffer ;
1124- XPath_LoadBuffer (sPath , & buffer );
1125- if (buffer .pData == NULL ) return XFALSE ;
1168+ XPath_LoadBufferSize (sPath , & buffer , pSearch -> nMaxRead );
1169+ if (buffer .pData == NULL ) return XSTDNON ;
11261170
11271171 char * pBuffer = (char * )buffer .pData ;
11281172 if (pSearch -> bInsensitive ) xstrcase ((char * )pBuffer , XSTR_LOWER );
11291173 int nPosit = xstrsrc (pBuffer , pSearch -> sText );
11301174
1175+ if (nPosit >= 0 && pSearch -> bSearchLines )
1176+ {
1177+ xarray_t * pArr = xstrsplite (pBuffer , "\n" );
1178+ if (pArr != NULL )
1179+ {
1180+ size_t i = 0 ;
1181+ for (i = 0 ; i < pArr -> nUsed ; i ++ )
1182+ {
1183+ char * pLine = (char * )XArray_GetData (pArr , i );
1184+ if (xstrsrc (pLine , pSearch -> sText ) >= 0 )
1185+ {
1186+ xfile_entry_t * pEntry = XFile_NewEntry (pName , pPath , pStat );
1187+ if (pEntry == NULL )
1188+ {
1189+ XFile_ErrorCallback (pSearch , "Failed to alloc entry: %s" , pPath );
1190+ XByteBuffer_Clear (& buffer );
1191+ XArray_Destroy (pArr );
1192+ return XSTDERR ;
1193+ }
1194+
1195+ while (* pLine && isspace ((unsigned char )* pLine )) pLine ++ ;
1196+ xstrncpy (pEntry -> sLine , sizeof (pEntry -> sLine ), pLine );
1197+ pEntry -> nLineNum = i + 1 ;
1198+
1199+ if (XFile_SearchCallback (pSearch , pEntry ) < 0 )
1200+ {
1201+ XByteBuffer_Clear (& buffer );
1202+ XArray_Destroy (pArr );
1203+ return XSTDERR ;
1204+ }
1205+ }
1206+ }
1207+ }
1208+
1209+ XByteBuffer_Clear (& buffer );
1210+ XArray_Destroy (pArr );
1211+ return XSTDNON ;
1212+ }
1213+
11311214 XByteBuffer_Clear (& buffer );
1132- if (nPosit < 0 ) return XFALSE ;
1215+ if (nPosit < 0 ) return XSTDNON ;
11331216 }
11341217
1135- return XTRUE ;
1218+ return XSTDOK ;
11361219}
11371220
11381221void XFile_SearchClearCb (xarray_data_t * pArrData )
@@ -1145,11 +1228,8 @@ void XFile_SearchClearCb(xarray_data_t *pArrData)
11451228static xarray_t * XFile_TokenizeName (xfile_search_t * pSrcCtx , const char * pFileName )
11461229{
11471230 xarray_t * pTokens = NULL ;
1148-
1149- if (xstrsrc (pFileName , ";" ) >= 0 )
1150- pTokens = xstrsplit (pFileName , ";" );
1151- else if (xstrsrc (pFileName , "*" ) >= 0 )
1152- return xstrsplit (pFileName , "*" );
1231+ if (xstrsrc (pFileName , "*" ) >= 0 ) return xstrsplit (pFileName , "*" );
1232+ if (xstrsrc (pFileName , ";" ) >= 0 ) pTokens = xstrsplit (pFileName , ";" );
11531233
11541234 if (pTokens == NULL ) return NULL ;
11551235 size_t i , nUsed = XArray_Used (pTokens );
@@ -1179,6 +1259,7 @@ static xarray_t* XFile_TokenizeName(xfile_search_t *pSrcCtx, const char *pFileNa
11791259void XFile_SearchInit (xfile_search_t * pSrcCtx , const char * pFileName )
11801260{
11811261 pSrcCtx -> bInsensitive = XFALSE ;
1262+ pSrcCtx -> bSearchLines = XFALSE ;
11821263 pSrcCtx -> bRecursive = XFALSE ;
11831264 pSrcCtx -> bMulty = XFALSE ;
11841265 pSrcCtx -> callback = NULL ;
@@ -1194,6 +1275,8 @@ void XFile_SearchInit(xfile_search_t *pSrcCtx, const char *pFileName)
11941275 pSrcCtx -> nFileTypes = 0 ;
11951276 pSrcCtx -> nLinkCount = -1 ;
11961277 pSrcCtx -> nFileSize = -1 ;
1278+ pSrcCtx -> nMaxRead = 0 ;
1279+ pSrcCtx -> nMaxSize = 0 ;
11971280
11981281 XArray_InitPool (& pSrcCtx -> fileArray , XSTDNON , XSTDNON , XFALSE );
11991282 pSrcCtx -> fileArray .clearCb = XFile_ArrayClearCb ;
@@ -1222,27 +1305,32 @@ xfile_entry_t* XFile_GetEntry(xfile_search_t *pSearch, int nIndex)
12221305
12231306int XFile_Search (xfile_search_t * pSearch , const char * pDirectory )
12241307{
1225- if (pDirectory == NULL || XSYNC_ATOMIC_GET (pSearch -> pInterrupted )) return XSTDERR ;
1226- size_t nDirLen = strlen ( pDirectory ) ;
1308+ if (XSYNC_ATOMIC_GET (pSearch -> pInterrupted ) ||
1309+ pDirectory == NULL ) return XSTDERR ;
12271310
12281311 xdir_t dirHandle ;
1229- if (XDir_Open (& dirHandle , pDirectory ) < 0 )
1312+ char sDirPath [XPATH_MAX ];
1313+
1314+ size_t nDirLen = strlen (pDirectory );
1315+ while (nDirLen && pDirectory [nDirLen -- ] == XSTR_SPACE_CHAR );
1316+ const char * pSlash = pDirectory [nDirLen ] == '/' ? XSTR_EMPTY : "/" ;
1317+ xstrncpyf (sDirPath , sizeof (sDirPath ), "%s%s" , pDirectory , pSlash );
1318+
1319+ if (XDir_Open (& dirHandle , sDirPath ) < 0 )
12301320 {
1231- XFile_ErrorCallback (pSearch , "Failed to open directory: %s" , pDirectory );
1321+ XFile_ErrorCallback (pSearch , "Failed to open directory: %s" , sDirPath );
12321322 return XSYNC_ATOMIC_GET (pSearch -> pInterrupted ) ? XSTDERR : XSTDOK ;
12331323 }
12341324
1325+ if (xstrused (pSearch -> sText ) && pSearch -> bInsensitive )
1326+ xstrcase (pSearch -> sText , XSTR_LOWER );
1327+
12351328 while (XDir_Read (& dirHandle , NULL , 0 ) > 0 && !XSYNC_ATOMIC_GET (pSearch -> pInterrupted ))
12361329 {
12371330 char sFullPath [XPATH_MAX ];
1238- char sDirPath [XPATH_MAX ];
12391331 xstat_t statbuf ;
12401332
1241- /* Don't add slash twice if directory already contains slash character at the end */
1242- const char * pSlash = (pDirectory [nDirLen - 1 ] != '/' ) ? "/" : XSTR_EMPTY ;
12431333 const char * pEntryName = dirHandle .pCurrEntry ;
1244-
1245- xstrncpyf (sDirPath , sizeof (sDirPath ), "%s%s" , pDirectory , pSlash );
12461334 xstrncpyf (sFullPath , sizeof (sFullPath ), "%s%s" , sDirPath , pEntryName );
12471335
12481336 if (xstat (sFullPath , & statbuf ) < 0 )
@@ -1252,7 +1340,8 @@ int XFile_Search(xfile_search_t *pSearch, const char *pDirectory)
12521340 continue ;
12531341 }
12541342
1255- if (XFile_CheckCriteria (pSearch , sDirPath , pEntryName , & statbuf ))
1343+ int nMatch = XFile_CheckCriteria (pSearch , sDirPath , pEntryName , & statbuf );
1344+ if (nMatch > 0 )
12561345 {
12571346 xfile_entry_t * pEntry = XFile_NewEntry (pEntryName , sDirPath , & statbuf );
12581347 if (pEntry == NULL )
@@ -1268,6 +1357,11 @@ int XFile_Search(xfile_search_t *pSearch, const char *pDirectory)
12681357 return XSTDERR ;
12691358 }
12701359 }
1360+ else if (nMatch < 0 )
1361+ {
1362+ XDir_Close (& dirHandle );
1363+ return XSTDERR ;
1364+ }
12711365
12721366 /* Recursive search */
12731367 if (pSearch -> bRecursive &&
0 commit comments