#include Once "window9.bi"

#include Once "crt/linux/unistd.bi"

#include "datetime.bi"

#define DT_UNKNOWN 0

#define DT_FIFO	1

#define DT_CHR	2

#define DT_DIR	4

#define DT_BLK	6

#define DT_REG	8

#define DT_LNK	10

#define DT_SOCK	12

#define DT_WHT 14

#define S_IWUSR &o200

#define S_IWGRP &o20

#define S_IWOTH &o2

#define S_IFMT  &o170000

#define S_IFSOCK &o140000

#define S_IFLNK	 &o120000

#define S_IFREG  &o100000

#define S_IFBLK  &o60000

#define S_IFDIR  &o40000

#define S_IFCHR  &o20000

#define S_IFIFO  &o10000

#define S_ISUID  &o4000

#define S_ISGID  &o2000

#define S_ISVTX  &o1000

#define S_ISLNK(m)	(((m) And S_IFMT) = S_IFLNK)

#define S_ISREG(m)	(((m) And S_IFMT) = S_IFREG)

#define S_ISDIR(m)	(((m) And S_IFMT) = S_IFDIR)

#define S_ISCHR(m)	(((m) And S_IFMT) = S_IFCHR)

#define S_ISBLK(m)	(((m) And S_IFMT) = S_IFBLK)

#define S_ISFIFO(m)	(((m) And S_IFMT) = S_IFIFO)

#define S_ISSOCK(m)	(((m) And S_IFMT) = S_IFSOCK)


Type dirent
	
	As Integer d_ino
	
	As Integer d_off
	
	As Unsigned Short d_reclen
	
	As Ubyte d_type
	
	As Zstring*256 d_name
	
End Type

Extern "C"
	
	Type _stat
		
		st_dev As dev_t
		
		#ifndef __fb_64bit__
			
			pad1 As Long
			
			st_ino As ino_t
			
			st_mode As mode_t
			
			st_nlink As nlink_t
			
		#else
			
			st_ino As ino_t
			
			st_nlink As nlink_t
			
			st_mode As mode_t	
			
		#endif
		
		st_uid As uid_t
		
		st_gid As gid_t
		
		st_rdev As dev_t
		
		#ifndef __fb_64bit__
			
			pad2 As Long
			
		#endif
		
		st_size As off_t
		
		st_atime As time_t
		
		st_atime_usec As time_t
		
		st_mtime As time_t
		
		st_mtime_usec As time_t
		
		st_ctime As time_t
		
		st_ctime_usec As time_t
		
		st_blksize As Uinteger 'blksize_t
		
		st_blocks As blkcnt_t
		
		st_reserve(200) as Byte ' simple free space memory in the structure and just in case
		
	End Type
	
	Declare Function stat (Byval As Zstring Ptr, Byval As _stat Ptr) As Long 
	
	Declare Function opendir (szName As Zstring Ptr) As Any Ptr
	
	Declare Function readdir (pOD As Any Ptr) As dirent Ptr
	
	Declare Function closedir (pOD As Any Ptr) As Integer	
	
End Extern		


Type TWIN9DIR
	
	sInitDir As Zstring*2000
	
	sCurentDir As Zstring*256
	
	sPattern As Zstring*256
	
	iOutAttr As Uinteger 
	
	tBuf As _stat Ptr
	
	hFind  As Any Ptr
	
End Type

Private Function getAttr(sFile As String , info As _stat Ptr , bATDir As Byte) As Integer
	
	Dim As Integer iAttributRet , mask
	
	If info->st_uid = geteuid() Then
		
		mask = S_IWUSR
		
	Elseif info->st_gid = getegid() Then
		
		mask = S_IWGRP
		
	Else
		
		mask = S_IWOTH
		
	Endif	
	
	If (info->st_mode And mask) = 0 Then
		
		iAttributRet = 1 ' read only
		
	Endif
	
	If Left(sFile,1) = "." Then
		
		iAttributRet Or=2 ' hidden
		
	Endif
	
	If S_ISCHR( info->st_mode ) Orelse S_ISBLK( info->st_mode ) Orelse S_ISFIFO( info->st_mode ) Orelse S_ISSOCK( info->st_mode )  Then
		
		iAttributRet Or=4 ' system
		
	Endif
	
	If S_ISDIR( info->st_mode ) Then
		
		iAttributRet Or= &h10 'directory 
		
		If (bATDir And DT_LNK) Then
			
			iAttributRet Or= 4 ' Link
			
		Endif		
		
	Else
		
		iAttributRet Or = &h20 ' archive
		
	Endif	
	
	Return iAttributRet
	
End Function 

Function Examinedirectory(sDirectoryName As String , sPattern As String) As Integer Export
	
	Dim As _stat Ptr tempBuf
	
	Dim As dirent Ptr pDirent
	
	Dim As Any Ptr hFind
	
	If Len(sDirectoryName) Andalso Len(sPattern) Then
		
		Dim As String sPatternTemp
		
		Dim wdir As TWIN9DIR Ptr = New TWIN9DIR
		
		if wdir = 0 then
			
			print "Allocated memory error in Examinedirectory!"
			
			return 0
			
		EndIf
		
		If Right(sDirectoryName , 1) <> "/" Then 
			
			wdir->sInitDir = sDirectoryName & "/"
			
		Else
			
			wdir->sInitDir = sDirectoryName 
			
		Endif
		
		Dim As dirent Ptr pDirent
		
		hFind  = opendir(wdir->sInitDir )
		
		If hFind = 0 Then 
			
			Delete wdir
			
			Return 0
			
		Endif
		
		pDirent = readdir(hFind)	
		
		If sPattern = "*.*" Orelse sPattern = "*." Orelse sPattern = ".*" Orelse sPattern = "*" Then
			
			sPatternTemp = "*"
			
			If pDirent = 0 Then
				
				closedir(hFind)
				
				Delete wdir
				
				Return 0
				
			Endif 			
			
		Else
			
			sPatternTemp = Trim(sPattern, "*")
			
			Do
				
				If pDirent = 0 Then
					
					closedir(hFind)
					
					Delete wdir
					
					Return 0
					
				Endif 
				
				If Instr(pDirent->d_name , sPatternTemp) Then 
					
					Exit Do
					
				Endif
				
				pDirent = readdir(hFind)
				
			Loop			
			
		Endif
		
		wdir->sCurentDir = pDirent->d_name
		
		wdir->sPattern = sPatternTemp
		
		tempBuf = Callocate (Sizeof(_stat)+100)
		
		if tempBuf then
			
			stat(wdir->sInitDir & wdir->sCurentDir, tempBuf)
			
			wdir->iOutAttr = getAttr(pDirent->d_name, tempBuf, pDirent->d_type)
			
			wdir->tBuf = tempBuf
			
			wdir->hFind = hFind
			
			Return Cast(Integer,wdir)
			
		else
			
			print "Allocated memory error in Examinedirectory!"
			
		endif
		
	Endif
	
End Function

Function Directoryentryattributes (hDir As Integer) As Uinteger Export
	
	Return (Cast(TWIN9DIR Ptr, hDir))->iOutAttr
	
End Function

Function Nextdirectoryentry(hDir As Integer) As Integer Export
	
	Dim As String sDir , sPattern
	
	Dim As dirent Ptr pDirent
	
	pDirent = readdir((Cast(TWIN9DIR Ptr, hDir))->hFind)
	
	sPattern = (Cast(TWIN9DIR Ptr, hDir))->sPattern
	
	If sPattern = "*" Then 
		
		If pDirent = 0 Then
			
			Return 0
			
		Endif		
		
	Else
		
		Do
			
			If pDirent = 0 Then
				
				Return 0
				
			Endif 
			
			If Instr(pDirent->d_name , sPattern) Then 
				
				Exit Do
				
			Endif
			
			pDirent = readdir((Cast(TWIN9DIR Ptr, hDir))->hFind)
			
		Loop			
		
	Endif	
	
	(Cast(TWIN9DIR Ptr, hDir))->sCurentDir = pDirent->d_name
	
	stat((Cast(TWIN9DIR Ptr, hDir))->sInitDir & (Cast(TWIN9DIR Ptr, hDir))->sCurentDir, ((Cast(TWIN9DIR Ptr, hDir))->tBuf))
	
	(Cast(TWIN9DIR Ptr, hDir))->iOutAttr = getAttr(pDirent->d_name, ((Cast(TWIN9DIR Ptr, hDir))->tBuf), pDirent->d_type)
	
	If (Cast(TWIN9DIR Ptr, hDir))->sCurentDir <> "" Then 
		
		Return 1
		
	Endif
	
End Function

Sub Finishdirectory(hDir As Integer) Export
	
	if (Cast(TWIN9DIR Ptr, hDir)->tBuf) then Deallocate (Cast(TWIN9DIR Ptr, hDir)->tBuf)
	
	closedir(Cast(TWIN9DIR Ptr, hDir)->hFind)
	
	if (Cast(TWIN9DIR Ptr, hDir)) then Delete (Cast(TWIN9DIR Ptr, hDir))
	
End Sub

Function Directoryentryname(hDir As Integer) As String Export
	
	Return (Cast(TWIN9DIR Ptr, hDir))->sCurentDir
	
End Function

Function Directoryentrysize(hDir As Integer) As Ulongint Export
	
	Return (Cast(TWIN9DIR Ptr, hDir))->tBuf->st_size
	
End Function

Function Directoryentrydate(hDir As Integer , iFlag As Long) As String Export
	
	Dim tinf As tm Ptr
	
	Dim dSerial As Double
	
	Dim As TWIN9DIR Ptr wDir = Cast(TWIN9DIR Ptr, hDir)
	
	Select Case iFlag
			
		Case 1
			
			tinf = localtime(@(wDir->tBuf->st_atime))
			
		Case 2
			
			tinf = localtime(@(wDir->tBuf->st_mtime))
			
		Case 3
			
			tinf = localtime(@(wDir->tBuf->st_ctime))
			
	End Select
	
	If tinf Then
		
		dSerial = Dateserial(1900 + tinf->tm_year, 1 + tinf->tm_mon, tinf->tm_mday) _
		+ Timeserial(tinf->tm_hour, tinf->tm_min, tinf->tm_sec)
		
		Dim As Integer _
		_
		iDay = Day(dSerial) ,_
		iMonth = Month(dSerial) , _
		iYear = Year(dSerial),_
		iHour = Hour(dSerial),_
		iMinute = Minute(dSerial),_
		iSecond = Second(dSerial)
		
		Dim As String sDay , sMonth , sHour , sMinute , sSecond
		
		If iDay < 10 Then
			
			sDay = "0" & iDay
			
		Else
			
			sDay = Str(iDay)
			
		Endif
		
		If iMonth < 10 Then
			
			sMonth = "0" & iMonth
			
		Else
			
			sMonth = Str(iMonth)
			
		Endif
		
		If iHour < 10 Then
			
			sHour = "0" & iHour
			
		Else
			
			sHour = Str(iHour)
			
		Endif
		
		If iMinute < 10 Then
			
			sMinute = "0" & iMinute
			
		Else
			
			sMinute = Str(iMinute)
			
		Endif
		
		If iSecond < 10 Then
			
			sSecond = "0" & iSecond
			
		Else
			
			sSecond = Str(iSecond)
			
		Endif
		
		Return sDay & "." & sMonth & "." & iYear & " " & sHour & ":" & sMinute & ":" & sSecond
		
		
	Endif
	
End Function

Function w9isFile(sFileName As String) As Long
	
	Dim As _stat Ptr tempBuf
	
	tempBuf = Callocate (Sizeof(_stat)+100)
	
	if tempBuf then
		
		stat( Strptr(sFileName) , tempBuf)
		
		If S_ISDIR( tempBuf->st_mode ) = 0 Then
			
			Function = 1
			
		Endif
		
		Deallocate(tempBuf)
		
	else
		
		print "Allocated memory error in w9isFile!"
		
	endif
	
End Function

Function w9isFileExists(sFileName As String) As Long
	
	Dim As HANDLE h = Read_file(sFileName)
	
	If h <> Cast(Any Ptr, -1) Then
		
		Function = 1
		
		Close_file(h)
		
	Endif
	
End Function

Function w9isDirExists(sFileName As String) As Long
	
	Dim As _stat Ptr tempBuf
	
	tempBuf = Callocate (Sizeof(_stat)+100)
	
	if tempBuf then
		
		stat( Strptr(sFileName) , tempBuf)
		
		If S_ISDIR( tempBuf->st_mode ) Then
			
			Function = 1
			
		Endif
		
		Deallocate(tempBuf)
		
	else
		
		print "Allocated memory error in w9isDirExists!"
		
	endif
	
End Function