turbonss-analyze: most memberships
This commit is contained in:
parent
8ceacc04b8
commit
bd13e6a322
@ -86,15 +86,15 @@ pub fn iterator(section: []const u8, total: u32) Iterator {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn gid(self: *const PackedGroup) u32 {
|
||||
pub inline fn gid(self: *const PackedGroup) u32 {
|
||||
return self.inner.gid;
|
||||
}
|
||||
|
||||
pub fn membersOffset(self: *const PackedGroup) u64 {
|
||||
pub inline fn membersOffset(self: *const PackedGroup) u64 {
|
||||
return self.members_offset;
|
||||
}
|
||||
|
||||
pub fn name(self: *const PackedGroup) []const u8 {
|
||||
pub inline fn name(self: *const PackedGroup) []const u8 {
|
||||
return self.groupdata;
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,11 @@ const Allocator = std.mem.Allocator;
|
||||
const BoundedArray = std.BoundedArray;
|
||||
|
||||
const flags = @import("flags.zig");
|
||||
const compress = @import("compress.zig");
|
||||
const DB = @import("DB.zig");
|
||||
const File = @import("File.zig");
|
||||
const PackedUser = @import("PackedUser.zig");
|
||||
const PackedGroup = @import("PackedGroup.zig");
|
||||
const Header = @import("header.zig").Header;
|
||||
const section_length_bits = @import("header.zig").section_length_bits;
|
||||
|
||||
@ -61,12 +63,12 @@ fn execute(
|
||||
const myflags = flags.parse(argv, &[_]flags.Flag{
|
||||
.{ .name = "-h", .kind = .boolean },
|
||||
}) catch {
|
||||
stderr.writeAll(usage) catch {};
|
||||
stderr.writeAll(usage) catch return 3;
|
||||
return 1;
|
||||
};
|
||||
|
||||
if (myflags.boolFlag("-h")) {
|
||||
stdout.writeAll(usage) catch return 1;
|
||||
stdout.writeAll(usage) catch return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -74,8 +76,8 @@ fn execute(
|
||||
0 => "/etc/turbonss/db.turbo",
|
||||
1 => mem.span(myflags.args[0]),
|
||||
else => {
|
||||
stderr.print("ERROR: too many arguments\n", .{}) catch {};
|
||||
stderr.writeAll(usage) catch {};
|
||||
stderr.print("ERROR: too many arguments\n", .{}) catch return 3;
|
||||
stderr.writeAll(usage) catch return 3;
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
@ -133,14 +135,54 @@ fn execute(
|
||||
\\Users: {[users]d}
|
||||
\\Groups: {[groups]d}
|
||||
\\Shells: {[shells]d}
|
||||
\\Sections:
|
||||
\\ Name Begin End Size bytes
|
||||
\\
|
||||
;
|
||||
stdout.print(template, info) catch {};
|
||||
stdout.print(template, info) catch return 3;
|
||||
|
||||
// Popularity contest:
|
||||
// - user with most groups
|
||||
// - TODO: group with most users. Not trivial, because
|
||||
// group memberships do not include users whose primary
|
||||
// gid is the target one.
|
||||
if (db.header.num_users > 0) {
|
||||
const Name = BoundedArray(u8, 32);
|
||||
const Popular = struct {
|
||||
name: Name = Name.init(0) catch unreachable,
|
||||
score: u64 = 0,
|
||||
};
|
||||
|
||||
var popUser = Popular{};
|
||||
var it = PackedUser.iterator(
|
||||
db.users,
|
||||
db.header.num_users,
|
||||
db.shellReader(),
|
||||
);
|
||||
while (it.next()) |packed_user| {
|
||||
const offset = packed_user.additional_gids_offset;
|
||||
const additional_gids = db.additional_gids[offset..];
|
||||
const vit = compress.varintSliceIteratorMust(additional_gids);
|
||||
// the primary gid of the user is never in "additional gids"
|
||||
const ngroups = vit.remaining + 1;
|
||||
if (ngroups > popUser.score) {
|
||||
const name = packed_user.name();
|
||||
popUser.name = Name.fromSlice(name) catch unreachable;
|
||||
popUser.score = ngroups;
|
||||
}
|
||||
}
|
||||
|
||||
stdout.print("Most memberships: {s} ({d})\n", .{
|
||||
popUser.name.constSlice(),
|
||||
popUser.score,
|
||||
}) catch return 3;
|
||||
}
|
||||
|
||||
var lengths = DB.fieldLengths(db.header);
|
||||
var offsets = DB.fieldOffsets(lengths);
|
||||
stdout.writeAll(
|
||||
\\Sections:
|
||||
\\ Name Begin End Size bytes
|
||||
\\
|
||||
) catch return 3;
|
||||
|
||||
inline for (meta.fields(DB.DBNumbers)) |field| {
|
||||
const length = @field(lengths, field.name);
|
||||
@ -151,7 +193,7 @@ fn execute(
|
||||
start << section_length_bits,
|
||||
end << section_length_bits,
|
||||
splitInt(length << section_length_bits).constSlice(),
|
||||
}) catch {};
|
||||
}) catch return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user