Code: Select all
;- ● TOP
EnableExplicit
;- # Constants
Enumeration Gadget
#cnv
#LV
#cb
#Editor
EndEnumeration
Enumeration Menu
#fsck
#umount
EndEnumeration
#Window = 0
#Win1 = 1
#Menu = 0
; https://www.purebasic.fr/english/viewtopic.php?f=12&t=71693
XIncludeFile "RunAsAdmin.pbi"
If Not RunAsAdmin::Login()
End
EndIf
Structure Disk2
name.s
uuid.s
mountpoint.s
fstype.s
label.s
size.s
rota.s
tran.s
EndStructure
Define tmp$, item
;- ● Global
Global NewList Drive.Disk2()
Global Children
Procedure.s GetField(Value.s)
Protected tmp, res$
tmp = GetJSONMember(Children, Value)
If tmp
Select JSONType(tmp)
Case #PB_JSON_Boolean
res$ = Str(GetJSONBoolean(tmp))
Case #PB_JSON_Null
res$ = "-"
Case #PB_JSON_String
res$ = GetJSONString(tmp)
EndSelect
EndIf
ProcedureReturn res$
EndProcedure
Procedure GetDriveInfo()
Protected res$, tmp
Protected Blockdevices, ObjectBlockdevices, hJSON, i, j, ObjectChildren, BD1Children, oTran, Tran$
; получить список дисков
tmp = RunProgram("lsblk", "-J -n -o name,UUID,MOUNTPOINT,FSTYPE,LABEL,SIZE,ROTA,TRAN -I8", "", #PB_Program_Open | #PB_Program_Read)
res$ = Chr(13)
If tmp
While ProgramRunning(tmp)
If AvailableProgramOutput(tmp)
res$ + ReadProgramString(tmp) + Chr(13)
EndIf
Wend
CloseProgram(tmp)
EndIf
; res$ = ReplaceString(res$, Chr(13) + "sd", Chr(13))
res$ = Trim(res$, Chr(13))
; Анализировать JSON и получить список дисков в Drive()
hJSON = ParseJSON(#PB_Any, res$)
If hJSON
ObjectBlockdevices = GetJSONMember(JSONValue(hJSON), "blockdevices")
If ObjectBlockdevices
; Debug GetJSONString(ObjectBlockdevices)
For j = 0 To JSONArraySize(ObjectBlockdevices) - 1
Tran$ = ""
BD1Children = GetJSONElement(ObjectBlockdevices, j)
ObjectChildren = GetJSONMember(BD1Children, "children")
oTran = GetJSONMember(BD1Children, "tran")
If oTran And JSONType(oTran) = #PB_JSON_String
Tran$ = GetJSONString(oTran)
EndIf
; Debug GetJSONString(BD1Children)
If ObjectChildren
For i = 0 To JSONArraySize(ObjectChildren) - 1
Children = GetJSONElement(ObjectChildren, i)
AddElement(Drive())
Drive()\name = GetField("name")
Drive()\uuid = GetField("uuid")
Drive()\mountpoint = GetField("mountpoint")
Drive()\fstype = GetField("fstype")
Drive()\label = GetField("label")
Drive()\size = GetField("size")
Drive()\rota = GetField("rota")
If Drive()\rota = "1"
Drive()\rota = "hdd"
ElseIf Drive()\rota = "0"
Drive()\rota = "ssd"
EndIf
Drive()\tran = Tran$
; Trim(Drive(), #LF$)
; Drive() + #CR$
Next i
EndIf
Next j
EndIf
EndIf
EndProcedure
Procedure fsch()
Protected tmp
tmp = RunProgram("e2fsck", "-f -y -v -C 0 /dev/" + Drive()\name, "", #PB_Program_Open | #PB_Program_Read)
If tmp
While ProgramRunning(tmp)
If AvailableProgramOutput(tmp)
AddGadgetItem(#Editor, -1, ReadProgramString(tmp))
; WindowEvent()
EndIf
Wend
CloseProgram(tmp)
EndIf
EndProcedure
Procedure Report()
Protected hWnd
DisableWindow(#Window, 1)
OpenWindow(#Win1, 0, 0, 900, 600, "Check Disk", #PB_Window_SystemMenu | #PB_Window_ScreenCentered, WindowID(#Window))
EditorGadget(#Editor, 0 , 0 , 900, 600)
fsch()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
DisableWindow(#Window, 0)
CloseWindow(#Win1)
EndProcedure
Procedure ExeComStr(*Result.string, dev$)
Protected NewList String$(), Len=0, tmp, *Point
tmp = RunProgram("fdisk", "-l /dev/" + dev$, "", #PB_Program_Open | #PB_Program_Read)
If tmp
While ProgramRunning(tmp)
If AvailableProgramOutput(tmp)
; res$ + ReadProgramString(tmp) + Chr(10)
; StrFastAdd(FS, ReadProgramString(tmp) + Chr(10))
If AddElement(String$())
String$() = ReadProgramString(tmp); + Chr(10)
EndIf
EndIf
Wend
; подсчитываем длину данных
; Count = ListSize(String$())
ForEach String$()
Len + Len(String$())
Next
Len+ListSize(String$()) ; добавляем число переносов строк #LF$ по количеству данных
*Result\s = Space(Len)
*Point = @*Result\s
ForEach String$()
CopyMemoryString(String$()+#LF$, @*Point)
Next
ClearList(String$())
CloseProgram(tmp)
EndIf
; ProcedureReturn res$
EndProcedure
Global Text.String
GetDriveInfo()
ExeComStr(@Text, "sda")
; Debug Text\s
; MessageRequester("", Text\s)
; SetClipboardText(Text\s)
Structure Disk
Name.s
DiskSize.s
DiskType.i
DiskStart.q
DiskEnd.q
DiskSector.q
EndStructure
Global Size.q
Global WndW
Global SizePx.q
Global NewList Disks.Disk()
Procedure RegExp()
Protected NbFound
Protected Dim Result$(0)
#RegExp = 0
If CreateRegularExpression(#RegExp, "\A[^\r\n]+?\h\K(\d+)(?=\h[^\d]+\n)", #PB_RegularExpression_DotAll | #PB_RegularExpression_AnyNewLine)
NbFound = ExtractRegularExpression(0, Text\s, Result$())
If NbFound
Size = Val(Result$(0))
Else
MessageRequester("", "Unable to determine size")
ProcedureReturn 0
EndIf
EndIf
FreeRegularExpression(#RegExp)
ClearList(Disks())
; If CreateRegularExpression(#RegExp, "/dev/sd\w(\d+)[\h*]+(\d+)\h+(\d+)\h+(\d+)")
If CreateRegularExpression(#RegExp, "/dev/(sd\w\d+)[\h*]+(\d+)\h+(\d+)\h+(\d+)\h+([\d,]+[TGMKB])\h+([\da-f]+)")
If ExamineRegularExpression(#RegExp, Text\s)
While NextRegularExpressionMatch(#RegExp)
If AddElement(Disks())
Disks()\Name = RegularExpressionGroup(#RegExp, 1)
Disks()\DiskStart = Val(RegularExpressionGroup(#RegExp, 2))
Disks()\DiskEnd = Val(RegularExpressionGroup(#RegExp, 3))
Disks()\DiskSector = Val(RegularExpressionGroup(#RegExp, 4))
Disks()\DiskSize = RegularExpressionGroup(#RegExp, 5)
Disks()\DiskType= Val(RegularExpressionGroup(#RegExp, 6))
EndIf
Wend
EndIf
EndIf
FreeRegularExpression(#RegExp)
ProcedureReturn 1
EndProcedure
Procedure Draw()
Protected Found, bgcolor
SizePx = Size/WndW
ClearGadgetItems(#LV)
If StartDrawing(CanvasOutput(#cnv))
DrawingMode(#PB_2DDrawing_Transparent)
Box(0, 0, WndW, 88, $3f3f3f)
ForEach Disks()
bgcolor = RGB(Random($FF, $99), Random($FF, $99), Random($FF, $99))
Box(Disks()\DiskStart / SizePx, 0, Disks()\DiskSector / SizePx, 88, bgcolor)
DrawText(Disks()\DiskStart / SizePx + 5, 30, Disks()\Name + #CRLF$ + Disks()\DiskSize, 0, #PB_2DDrawing_Transparent)
Found = 0
ForEach Drive()
If Disks()\Name = Drive()\name
Found = 1
Break
EndIf
Next
If Found
AddGadgetItem(#LV, -1, Disks()\Name + Chr(10) + Disks()\DiskSize + Chr(10) + Disks()\DiskType +
Chr(10) + Drive()\label + Chr(10) + Drive()\mountpoint + Chr(10) + Drive()\fstype + Chr(10) + Drive()\uuid)
Else
AddGadgetItem(#LV, -1, Disks()\Name + Chr(10) + Disks()\DiskSize + Chr(10) + Disks()\DiskType)
EndIf
Next
StopDrawing()
EndIf
EndProcedure
ExamineDesktops()
WndW = DesktopWidth(0) - 50
;-┌──GUI──┐
If OpenWindow(#Window, 0, 0, WndW + 10, 444, "HDD", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
CanvasGadget(#cnv, 5, 0, WndW, 88, #PB_Canvas_Border)
ComboBoxGadget(#cb, 5, 400 , 90 , 30)
AddGadgetItem(#cb, -1, "sda")
AddGadgetItem(#cb, -1, "sdb")
AddGadgetItem(#cb, -1, "sdc")
AddGadgetItem(#cb, -1, "sdd")
AddGadgetItem(#cb, -1, "sde")
AddGadgetItem(#cb, -1, "sdf")
ListIconGadget(#LV, 5 , 93, WndW, 300, "Disks", 50)
AddGadgetColumn(#LV, 1, "Size", 60)
AddGadgetColumn(#LV, 2, "Type", 50)
AddGadgetColumn(#LV, 3, "Mark", 80)
AddGadgetColumn(#LV, 4, "mounting", 120)
AddGadgetColumn(#LV, 5, "fs", 50)
AddGadgetColumn(#LV, 6, "uuid", 150)
If RegExp()
Draw()
EndIf
If CreatePopupMenu(#Menu)
MenuItem(#umount, "Unmount disk")
MenuItem(#fsck, "Check Disk")
EndIf
;-┌──Loop──┐
Repeat
Select WaitWindowEvent()
;- ├ Gadget
Case #PB_Event_Gadget
Select EventGadget()
Case #LV
If EventType() = #PB_EventType_RightClick
item = GetGadgetState(#LV)
If item <> -1
DisplayPopupMenu(#Menu, WindowID(#Window))
EndIf
EndIf
Case #cb
If EventType() = #PB_EventType_Change
tmp$ = GetGadgetText(#cb)
ExeComStr(@Text, tmp$)
If RegExp()
Draw()
EndIf
EndIf
EndSelect
;- ├ Menu
Case #PB_Event_Menu
Select EventMenu()
Case #umount
item = GetGadgetState(#LV)
If item <> -1
tmp$ = GetGadgetItemText(#LV, item, 0)
ForEach Drive()
If tmp$ = Drive()\name
RunProgram("umount", "-l " + Drive()\mountpoint, "")
Break
EndIf
Next
EndIf
Case #fsck
item = GetGadgetState(#LV)
If item <> -1
tmp$ = GetGadgetItemText(#LV, item, 0)
ForEach Drive()
If tmp$ = Drive()\name
Report()
; RunProgram("e2fsck", "-f -y -v -C 0 /dev/" + Drive()\name, "")
; RunProgram("bash", "e2fsck -f -y -v -C 0 /dev/" + Drive()\name, "")
; RunProgram("bash", "-c " + #DQUOTE$ + "e2fsck -f -y -v -C 0 /dev/" + Drive()\name + #DQUOTE$, "")
Break
EndIf
Next
EndIf
EndSelect
Case #PB_Event_CloseWindow
CloseWindow(#Window)
End
EndSelect
ForEver
;-└───Loop───┘
EndIf