fs: pure Gio implementation; #272

This commit is contained in:
Luca CPZ 2018-02-16 17:21:09 +01:00
parent d1112da25d
commit 24ca5856dc
3 changed files with 71 additions and 461 deletions

View File

@ -1,397 +0,0 @@
#!/usr/bin/env bash
#
# Adapted from Eridan's "fs" (cleanup, enhancements and switch to bash/Linux)
# JM, 10/12/2004
#
# Integrated into Lain in september 2013
# https://github.com/lcpz/lain
# Requires gawk
# -------------------------------------------------------------------------
# Decoding options
# -------------------------------------------------------------------------
USAGE="Usage: $0 [-h(elp)] | [-n(arrow mode)] | [-w(eb output) | --type=<fstype> | --exclude-type=<fstype>]"
NARROW_MODE=0
WEB_OUTPUT=0
DF_OPTIONS=""
while [ $# -gt 0 ]; do
case "$1" in
"-h" )
echo $USAGE
exit
;;
"-d" )
DEBUG=1
;;
"-n" )
NARROW_MODE=1
;;
"-w" )
WEB_OUTPUT=1
;;
--type=*)
DF_OPTIONS+=" $1"
;;
--exclude-type=*)
DF_OPTIONS+=" $1"
;;
* )
echo $USAGE
exit
;;
esac
shift
done
# -------------------------------------------------------------------------
# Preparations
# -------------------------------------------------------------------------
SYSTEM=`uname -s`
PATTERN="/"
case "$SYSTEM" in
"Linux" )
DF_COMMAND="/usr/bin/env df -k"
SORT_COMMAND="/usr/bin/env sort -k6"
AWK_COMMAND="/usr/bin/env awk"
;;
* )
DF_COMMAND="/bin/df -k"
SORT_COMMAND="/usr/bin/sort -k6"
AWK_COMMAND="/usr/bin/env gawk"
;;
esac
# Add additional df options
DF_COMMAND+=$DF_OPTIONS
# -------------------------------------------------------------------------
# Grabbing "df" result
# -------------------------------------------------------------------------
DF_RESULT=`$DF_COMMAND`
if [ ! -z $DEBUG ]; then
echo "--> DF_RESULT:"
echo "$DF_RESULT"
echo ""
fi
# -------------------------------------------------------------------------
# Preprocessing "df" result, to join split logical lines
# -------------------------------------------------------------------------
PREPROCESSING_RESULT=` \
echo "$DF_RESULT" | $AWK_COMMAND -v PATTERN=$PATTERN \
'
NF == 1 {
printf ("%s", $0)
}
NF == 5 {
printf ("%s\n", $0)
}
NF > 6 {
}
NF == 6 {
printf ("%s\n", $0)
}'
`
if [ ! -z $DEBUG ]; then
echo "--> PREPROCESSING_RESULT:"
echo "$PREPROCESSING_RESULT"
echo ""
fi
SORTED_FILE_SYSTEMS_INFO=`echo "$PREPROCESSING_RESULT" | $SORT_COMMAND`
if [ ! -z $DEBUG ]; then
echo "--> SORTED_FILE_SYSTEMS_INFO:"
echo "$SORTED_FILE_SYSTEMS_INFO"
echo ""
fi
# -------------------------------------------------------------------------
# Computing mount point max length
# -------------------------------------------------------------------------
MOUNT_POINT_MAX_LENGTH=` \
echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \
'
BEGIN {
mount_point_length_max = 15;
}
END {
printf ("%d", mount_point_length_max);
}
$0 ~ PATTERN {
# printf ("$6 = %s\n", $6);
mount_point = $6;
# printf ("mount_point = %s\n", mount_point);
mount_point_length = length (mount_point);
# printf ("mount_point_length = %d\n", mount_point_length);
if (mount_point_length > mount_point_length_max)
mount_point_length_max = mount_point_length;
}'
`
if [ ! -z $DEBUG ]; then
echo "MOUNT_POINT_MAX_LENGTH: $MOUNT_POINT_MAX_LENGTH"
fi
# -------------------------------------------------------------------------
# Computing mount point data max size
# -------------------------------------------------------------------------
MOUNT_POINT_MAX_SIZE=` \
echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \
'
BEGIN {
mount_point_size_max = 0;
}
END {
printf ("%d", mount_point_size_max);
}
$0 ~ PATTERN {
# df -k shows k_bytes!
# printf ("$2 = %s\n", $2);
mount_point_size = $2 * 1024;
# printf ("mount_point_size = %d\n", mount_point_size);
if (mount_point_size > mount_point_size_max)
mount_point_size_max = mount_point_size;
}'
`
if [ ! -z $DEBUG ]; then
echo "MOUNT_POINT_MAX_SIZE: $MOUNT_POINT_MAX_SIZE"
fi
# -------------------------------------------------------------------------
# Let's go!
# -------------------------------------------------------------------------
echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATTERN -v NARROW_MODE=$NARROW_MODE -v LEFT_COLUMN=$MOUNT_POINT_MAX_LENGTH -v MAX_SIZE=$MOUNT_POINT_MAX_SIZE -v SCALE=$SCALE -v WEB_OUTPUT=$WEB_OUTPUT \
'
# {printf ("$0 = %s\n", $0);}
# {printf ("$1 = %s\n", $1);}
# {printf ("PATTERN = %s\n", PATTERN);}
# {printf ("LEFT_COLUMN = %s\n", LEFT_COLUMN);}
BEGIN {
k_bytes = 1024.0;
m_bytes = 1024.0 * k_bytes;
g_bytes = 1024.0 * m_bytes;
t_bytes = 1024.0 * g_bytes;
if (WEB_OUTPUT)
{
all_stars = "**************************************************";
current_date = strftime ("%d-%m-%Y @ %H:%M:%S", localtime (systime ()));
free_threshold = 10; # %
printf ("<!-- DEBUT CONTENU -->\n");
printf ( \
"<A NAME=\"top\"></A>\n" \
"<P ALIGN=CENTER><SPAN CLASS=\"titleblue\">%s</SPAN><SPAN CLASS=\"textbold\"> -- STATUS OF <SPAN CLASS=\"titlered\">ALCOR</SPAN> FILE SYSTEMS</SPAN></P><BR>\n",
current_date )
printf ("<TABLE WIDTH=\"100%%\" BORDER=1>\n");
printf ( \
"<TR>\n" \
"<TD ALIGN=LEFT><STRONG>Mount point</STRONG></TD>\n" \
"<TD ALIGN=CENTER><STRONG>%% Usato&nbsp;(<SPAN CLASS=\"titleblue\">*</SPAN>)" \
"&nbsp;-&nbsp;%% Free&nbsp;(<SPAN CLASS=\"titlegreen\">*</SPAN>)</STRONG></TD>\n" \
"<TD ALIGN=CENTER><STRONG>%% Used</STRONG></TD>\n" \
"<TD ALIGN=CENTER><STRONG>Free</STRONG></TD>\n" \
"<TD ALIGN=CENTER><STRONG>Total</STRONG></TD>\n" \
"</TR>\n" );
}
else
{
narrow_margin = " ";
# printf ("%-*s", LEFT_COLUMN + 2, "Mount point");
if (NARROW_MODE)
printf ("\n%s", narrow_margin);
else
printf ("%-*s", LEFT_COLUMN + 2, "");
print " Used Free Total ";
if (! NARROW_MODE)
print " ";
}
}
END {
if (WEB_OUTPUT)
{
printf ("</TABLE>\n");
printf ("<!-- FIN CONTENU -->\n");
}
else
{
if (NARROW_MODE)
printf ("%s", narrow_margin);
else
printf ("%-*s", LEFT_COLUMN + 2, "");
print "|----|----|----|----|----|----|----|----|----|----|"
if (NARROW_MODE)
printf ("\n%s", narrow_margin);
else
printf ("%-*s", LEFT_COLUMN + 2, "");
print "0 10 20 30 40 50 60 70 80 90 100";
print "";
}
}
$0 ~ PATTERN {
if (index ($0, "members") == 0 && index ($0, "Download") == 0 && index ($0, "admin") == 0)
{
# df -k shows k_bytes!
total_size = $2 * k_bytes;
free_size = $4 * k_bytes;
percentage_occupied = substr($5, 0, 3);
mount_point = $6;
percentage_free = int (100 - percentage_occupied);
# reduction_factor: 2
stars_number = int (percentage_occupied / 2);
if (WEB_OUTPUT)
{
posGroup = index (mount_point, "scratch");
if (posGroup == 0)
posGroup = index (mount_point, "u1");
if (posGroup == 0)
posGroup = index (mount_point, "u2");
if (posGroup == 0)
posGroup = index (mount_point, "u4");
if (posGroup == 0)
posGroup = index (mount_point, "u5");
printf ("<TR>\n");
if (posGroup > 0 || percentage_free < free_threshold)
{
if (percentage_free < free_threshold)
{
class = "titlered";
if (posGroup == 0)
posGroup = 1; # to display the whole mount_point in this color anyway
}
else if ((index (mount_point, "scratch") != 0) || (index (mount_point, "u1") != 0) || (index (mount_point, "u2") != 0))
{
class = "titleorange";
posGroup = 1; # to display the whole mount_point in this color
}
else if ((index (mount_point, "u4") != 0) || (index (mount_point, "u5") != 0))
{
class = "titlebrown";
posGroup = 1; # to display the whole mount_point in this color
}
printf ( \
"<TD ALIGN=LEFT>%s<SPAN CLASS=\"%s\">%s</SPAN></TD>\n",
substr (mount_point, 1, posGroup - 1),
class,
substr (mount_point, posGroup) );
}
else
{
printf ("<TD ALIGN=LEFT>%s</TD>\n", mount_point);
}
printf ( \
"<TD ALIGN=CENTER><SPAN CLASS=\"titleblue\">%s</SPAN><SPAN CLASS=\"titlegreen\">%s</SPAN></TD>\n",
substr (all_stars, 1, stars_number), substr (all_stars, stars_number + 1, 49) );
if (percentage_free < free_threshold)
{
color_beginning = "<SPAN CLASS=\"titlered\">";
color_end = "</SPAN>"
}
else
{
color_beginning = "";
color_end = ""
}
if (total_size > 1 * t_bytes)
printf ( \
"<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Tb</TD><TD ALIGN=RIGHT>%5.1f Tb</TD>\n", \
color_beginning, percentage_occupied, color_end, free_size / t_bytes, total_size / t_bytes \
);
else if (total_size > 1 * g_bytes)
printf ( \
"<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Gb</TD><TD ALIGN=RIGHT>%5.1f Gb</TD>\n", \
color_beginning, percentage_occupied, color_end, free_size / g_bytes, total_size / g_bytes \
);
else if (total_size > 1 * m_byptes)
printf ( \
"<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Mb</TD><TD ALIGN=RIGHT>%5.1f Mb</TD>\n", \
color_beginning, percentage_occupied, color_end, free_size / m_bytes, total_size / m_bytes \
);
else
printf ( \
"<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Kb</TD><TD ALIGN=RIGHT>%5.1f Kb</TD>\n", \
color_beginning, percentage_occupied, color_end, free_size / k_bytes, total_size / k_bytes \
);
printf ("</TR>\n");
}
else
{
# printf ("percentage_occupied = %d\n", percentage_occupied);
# printf ("percentage_free = %d\n", percentage_free);
printf ("%-*s", LEFT_COLUMN + 2, mount_point);
if (NARROW_MODE)
printf ("\n%s", narrow_margin);
# printf ("stars_number = %d\n", stars_number);
printf ("|");
for (i = 1; i <= stars_number && i <= 49; i++)
{
printf ("%s", "*");
}
for (i = stars_number + 1; i <= 49; i++)
{
printf ("%s", "-");
}
if (total_size > 1 * t_bytes)
printf ( \
"| %3d%% %6.1f %6.1f Tb\n", \
percentage_occupied, free_size / t_bytes, total_size / t_bytes \
);
else if (total_size > 1 * g_bytes)
printf ( \
"| %3d%% %6.1f %6.1f Gb\n", \
percentage_occupied, free_size / g_bytes, total_size / g_bytes \
);
else if (total_size > 1 * m_byptes)
printf ( \
"| %3d%% %6.1f %6.1f Mb\n", \
percentage_occupied, free_size / m_bytes, total_size / m_bytes \
);
else
printf ( \
"| %3d%% %6.1f %6.1f Kb\n", \
percentage_occupied, free_size / k_bytes, total_size / k_bytes \
);
}
} # if
}'

View File

@ -1,23 +1,38 @@
--[[
Licensed under GNU General Public License v2
* (c) 2018, Uli Schlacter
* (c) 2018, Otto Modinos
* (c) 2013, Luca CPZ
--]]
local helpers = require("lain.helpers")
local shell = require("awful.util").shell
local focused = require("awful.screen").focused
local wibox = require("wibox")
local naughty = require("naughty")
local string = string
local tonumber = tonumber
local helpers = require("lain.helpers")
local Gio = require("lgi").Gio
local focused = require("awful.screen").focused
local wibox = require("wibox")
local naughty = require("naughty")
local math = math
local sformat = string.format
local tconcat = table.concat
local tonumber = tonumber
local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED
local query = query_size .. "," .. query_free .. "," .. query_used
-- File system disk space usage
-- File systems info
-- lain.widget.fs
local function factory(args)
local fs = { unit = { ["mb"] = 1024, ["gb"] = 1024^2 }, widget = wibox.widget.textbox() }
local fs = {
widget = wibox.widget.textbox(),
units = {
[1] = "Kb", [2] = "Mb", [3] = "Gb",
[4] = "Tb", [5] = "Pb", [6] = "Eb",
[7] = "Zb", [8] = "Yb"
}
}
function fs.hide()
if not fs.notification then return end
@ -26,29 +41,20 @@ local function factory(args)
end
function fs.show(seconds, scr)
fs.update()
fs.hide()
if fs.followtag then
fs.notification_preset.screen = focused()
else
fs.notification_preset.screen = scr or 1
end
fs.notification = naughty.notify({
fs.hide(); fs.update()
fs.notification_preset.screen = fs.followtag and focused() or scr or 1
fs.notification = naughty.notify {
preset = fs.notification_preset,
timeout = seconds or 5
})
}
end
local args = args or {}
local timeout = args.timeout or 600
local partition = args.partition or "/"
local showpopup = args.showpopup or "on"
local notify = args.notify or "on"
local settings = args.settings or function() end
local args = args or {}
local timeout = args.timeout or 600
local partition = args.partition
local showpopup = args.showpopup or "on"
local settings = args.settings or function() end
fs.options = args.options
fs.followtag = args.followtag or false
fs.notification_preset = args.notification_preset
@ -60,54 +66,55 @@ local function factory(args)
}
end
helpers.set_map(partition, false)
function fs.update()
fs_info, fs_now = {}, {}
helpers.async({ shell, "-c", "/usr/bin/env LC_ALL=C df -k --output=target,size,used,avail,pcent" }, function(f)
for line in string.gmatch(f, "\n[^\n]+") do
local m,s,u,a,p = string.match(line, "(/.-%s).-(%d+).-(%d+).-(%d+).-([%d]+)%%")
m = m:gsub(" ", "") -- clean target from any whitespace
local notifytable = { [1] = sformat("%-10s %-5s %s\t%s\t\n", "fs", "used", "free", "size") }
fs_now = {}
fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / fs.unit["mb"])
fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / fs.unit["gb"])
fs_info[m .. " used_mb"] = string.format("%.1f", tonumber(u) / fs.unit["mb"])
fs_info[m .. " used_gb"] = string.format("%.1f", tonumber(u) / fs.unit["gb"])
fs_info[m .. " used_p"] = p
fs_info[m .. " avail_mb"] = string.format("%.1f", tonumber(a) / fs.unit["mb"])
fs_info[m .. " avail_gb"] = string.format("%.1f", tonumber(a) / fs.unit["gb"])
fs_info[m .. " avail_p"] = string.format("%d", 100 - tonumber(p))
for _, mount in ipairs(Gio.unix_mounts_get()) do
local path = Gio.unix_mount_get_mount_path(mount)
local root = Gio.File.new_for_path(path)
local info = root:query_filesystem_info(query)
local size = info:get_attribute_uint64(query_size)
local used = info:get_attribute_uint64(query_used)
local free = info:get_attribute_uint64(query_free)
if size > 0 then
local units = math.floor(math.log(size)/math.log(1024))
fs_now[path] = {
units = fs.units[units],
percentage = math.floor(100 * used / size), -- used percentage
size = size / math.pow(1024, math.floor(units)),
used = used / math.pow(1024, math.floor(units)),
free = free / math.pow(1024, math.floor(units))
}
-- don't notify unused file systems
if fs_now[path].percentage > 0 then
notifytable[#notifytable+1] = sformat("\n%-10s %-5s %3.2f\t%3.2f\t%s", path,
fs_now[path].percentage .. "%", fs_now[path].free, fs_now[path].size,
fs_now[path].units)
end
end
end
fs_now.size_mb = fs_info[partition .. " size_mb"] or "N/A"
fs_now.size_gb = fs_info[partition .. " size_gb"] or "N/A"
fs_now.used = fs_info[partition .. " used_p"] or "N/A"
fs_now.used_mb = fs_info[partition .. " used_mb"] or "N/A"
fs_now.used_gb = fs_info[partition .. " used_gb"] or "N/A"
fs_now.available = fs_info[partition .. " avail_p"] or "N/A"
fs_now.available_mb = fs_info[partition .. " avail_mb"] or "N/A"
fs_now.available_gb = fs_info[partition .. " avail_gb"] or "N/A"
widget = fs.widget
settings()
notification_preset = fs.notification_preset
widget = fs.widget
settings()
if notify == "on" and tonumber(fs_now.used) and tonumber(fs_now.used) >= 99 and not helpers.get_map(partition) then
naughty.notify({
if partition and fs_now[partition] and fs_now[partition].used >= 99 then
if not helpers.get_map(partition) then
naughty.notify {
preset = naughty.config.presets.critical,
title = "Warning",
text = partition .. " is full",
})
}
helpers.set_map(partition, true)
else
helpers.set_map(partition, false)
end
end)
end
local notifycmd = (fs.options and string.format("dfs %s", fs.options)) or "dfs"
helpers.async(helpers.scripts_dir .. notifycmd, function(ws)
fs.notification_preset.text = ws:gsub("\n*$", "")
end)
fs.notification_preset.text = tconcat(notifytable)
end
if showpopup == "on" then
@ -115,7 +122,7 @@ local function factory(args)
fs.widget:connect_signal('mouse::leave', function () fs.hide() end)
end
helpers.newtimer(partition, timeout, fs.update)
helpers.newtimer(partition or "fs", timeout, fs.update)
return fs
end

2
wiki

@ -1 +1 @@
Subproject commit 2859d4049cf9b96ffa8ac2c872428d730b6477c9
Subproject commit e8860c7593f86584b45ada7d5232f32915ba20a6