+-- Iterate through the maps listed in the given zprint(1) output `zpout`.
+function zprint.maps(zpout)
+ local maps = lines_inside_dashes(zpout, 5)
+ local lines = maps:gmatch('([^\n]+)')
+
+ return function()
+ -- Grab the next line.
+ local line = lines()
+ if not line then
+ return nil
+ end
+
+ -- The line can take on 3 different forms. Check for each of them
+
+ -- Check for 3 columns
+ local name, free_kb, largest_free_kb, curr_size_kb = line:match(
+ '(%S+)%s+(%d+)K%s+(%d+)K%s+(%d+)K')
+ local free, largest_free, peak_size_kb, peak_size, size
+ if not name then
+ -- Check for 2 columns
+ name, peak_size_kb, curr_size_kb = line:match('(%S+)%s+(%d+)K%s+(%d+)K')
+ if not name then
+ -- Check for a single column
+ name, curr_size_kb = line:match('(%S+)%s+(%d+)K')
+ assert(name)
+ else
+ peak_size = tonumber(peak_size_kb) * 1024
+ end
+ else
+ free = tonumber(free_kb) * 1024
+ largest_free = tonumber(largest_free_kb) * 1024
+ end
+ size = tonumber(curr_size_kb) * 1024
+
+ return {
+ name = name,
+ size = size,
+ max_size = peak_size,
+ free = free,
+ largest_free = largest_free
+ }
+ end
+end
+
+-- Iterate through the zone views listed in the given zprint(1) output `zpout`.
+function zprint.zone_views(zpout)
+ -- Skip to the zone views
+ local prev_pos = 1
+ -- Look for a line that starts with "zone views" and is followed by a -- line.
+ while true do
+ local start_pos, end_pos = zpout:find('\n[-]+\n', prev_pos)
+ if start_pos == nil then
+ return nil
+ end
+ local before = zpout:sub(prev_pos, start_pos)
+ local zone_views_index = zpout:find('\n%s*zone views%s+[^\n]+\n', prev_pos + 1)
+ prev_pos = end_pos
+ if zone_views_index and zone_views_index < end_pos then
+ break
+ end
+ end
+
+ local zone_views
+ local zone_totals_index = zpout:find("\nZONE TOTALS")
+ if zone_totals_index then
+ zone_views = zpout:sub(prev_pos + 1, zone_totals_index)
+ else
+ zone_views = zpout:sub(prev_pos+ 1)
+ end
+
+ local lines = zone_views:gmatch('([^\n]+)')
+
+ return function()
+ -- Grab the next line.
+ local line = lines()
+ if not line then
+ return nil
+ end
+
+ local name, curr_size_kb = line:match('(%S+)%s+(%d+)')
+ local size = tonumber(curr_size_kb) * 1024
+
+ return {
+ name = name,
+ size = size,
+ }
+ end
+end
+