this repo has no description
56
fork

Configure Feed

Select the types of activity you want to include in your feed.

fmt: print group

+71 -2
+71 -2
src/main.zig
··· 92 92 .cb = onCompletion, 93 93 .msg = @intFromEnum(Msg.passwd), 94 94 }); 95 + _ = try ring.open("/etc/group", .{ .CLOEXEC = true }, 0, .{ 96 + .ptr = &cmd, 97 + .cb = onCompletion, 98 + .msg = @intFromEnum(Msg.group), 99 + }); 95 100 } 96 101 97 102 try ring.run(.until_done); ··· 106 111 const one_year_ago = try now.subtract(.{ .days = 365 }); 107 112 for (cmd.entries) |entry| { 108 113 const user = cmd.getUser(entry.statx.uid).?; 114 + const group = cmd.getGroup(entry.statx.gid).?; 109 115 const ts = @as(i128, entry.statx.mtime.sec) * std.time.ns_per_s; 110 116 const inst: zeit.Instant = .{ .timestamp = ts, .timezone = &tz }; 111 117 const time = inst.time(); 112 118 113 119 if (ts > one_year_ago.timestamp) { 114 - try bw.writer().print("{s} {s} {d: >2} {s} {d: >2}:{d:0>2} {s}\r\n", .{ 120 + try bw.writer().print("{s} {s} {s} {d: >2} {s} {d: >2}:{d:0>2} {s}\r\n", .{ 115 121 &entry.modeStr(), 116 122 user.name, 123 + group.name, 117 124 time.day, 118 125 time.month.shortName(), 119 126 time.hour, ··· 121 128 entry.name, 122 129 }); 123 130 } else { 124 - try bw.writer().print("{s} {s} {d: >2} {s} {d: >5} {s}\r\n", .{ 131 + try bw.writer().print("{s} {s} {s} {d: >2} {s} {d: >5} {s}\r\n", .{ 125 132 &entry.modeStr(), 126 133 user.name, 134 + group.name, 127 135 time.day, 128 136 time.month.shortName(), 129 137 time.year, ··· 148 156 entries: []Entry = &.{}, 149 157 150 158 tz: ?zeit.TimeZone = null, 159 + groups: std.ArrayListUnmanaged(Group) = .empty, 151 160 users: std.ArrayListUnmanaged(User) = .empty, 152 161 153 162 fn getUser(self: Command, uid: posix.uid_t) ?User { ··· 156 165 } 157 166 return null; 158 167 } 168 + 169 + fn getGroup(self: Command, gid: posix.gid_t) ?Group { 170 + for (self.groups.items) |group| { 171 + if (group.gid == gid) return group; 172 + } 173 + return null; 174 + } 159 175 }; 160 176 161 177 const Msg = enum(u16) { 162 178 cwd, 163 179 localtime, 164 180 passwd, 181 + group, 165 182 stat, 166 183 167 184 read_localtime, 168 185 read_passwd, 186 + read_group, 169 187 }; 170 188 171 189 const User = struct { ··· 174 192 175 193 fn lessThan(_: void, lhs: User, rhs: User) bool { 176 194 return lhs.uid < rhs.uid; 195 + } 196 + }; 197 + 198 + const Group = struct { 199 + gid: posix.gid_t, 200 + name: []const u8, 201 + 202 + fn lessThan(_: void, lhs: Group, rhs: Group) bool { 203 + return lhs.gid < rhs.gid; 177 204 } 178 205 }; 179 206 ··· 332 359 cmd.users.appendAssumeCapacity(user); 333 360 } 334 361 std.mem.sort(User, cmd.users.items, {}, User.lessThan); 362 + }, 363 + 364 + .group => { 365 + const fd = try result.open; 366 + 367 + const buffer = try cmd.arena.alloc(u8, 8192); 368 + _ = try io.read(fd, buffer, .{ 369 + .cb = onCompletion, 370 + .ptr = cmd, 371 + .msg = @intFromEnum(Msg.read_group), 372 + }); 373 + }, 374 + 375 + .read_group => { 376 + const n = try result.read; 377 + _ = try io.close(task.req.read.fd, .{}); 378 + const bytes = task.req.read.buffer[0..n]; 379 + 380 + var lines = std.mem.splitScalar(u8, bytes, '\n'); 381 + 382 + var line_count: usize = 0; 383 + while (lines.next()) |_| { 384 + line_count += 1; 385 + } 386 + try cmd.groups.ensureUnusedCapacity(cmd.arena, line_count); 387 + lines.reset(); 388 + // <name>:<throwaway>:<uid><...garbage> 389 + while (lines.next()) |line| { 390 + if (line.len == 0) continue; 391 + var iter = std.mem.splitScalar(u8, line, ':'); 392 + const name = iter.first(); 393 + _ = iter.next(); 394 + const gid = iter.next().?; 395 + 396 + const group: Group = .{ 397 + .name = name, 398 + .gid = try std.fmt.parseInt(u32, gid, 10), 399 + }; 400 + 401 + cmd.groups.appendAssumeCapacity(group); 402 + } 403 + std.mem.sort(Group, cmd.groups.items, {}, Group.lessThan); 335 404 }, 336 405 337 406 else => {},