handle duplicate gid
This commit is contained in:
parent
e6b9d43646
commit
eaccd00960
@ -5,6 +5,7 @@ const sort = std.sort;
|
|||||||
const unicode = std.unicode;
|
const unicode = std.unicode;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
const AutoHashMap = std.AutoHashMap;
|
||||||
const StringHashMap = std.StringHashMap;
|
const StringHashMap = std.StringHashMap;
|
||||||
const MultiArrayList = std.MultiArrayList;
|
const MultiArrayList = std.MultiArrayList;
|
||||||
const ArrayListUnmanaged = std.ArrayListUnmanaged;
|
const ArrayListUnmanaged = std.ArrayListUnmanaged;
|
||||||
@ -69,20 +70,43 @@ pub fn init(
|
|||||||
for (groups_arr) |group|
|
for (groups_arr) |group|
|
||||||
groups.appendAssumeCapacity(group);
|
groups.appendAssumeCapacity(group);
|
||||||
|
|
||||||
|
// verify whatever comes to cmph are unique: user names
|
||||||
var name2user = StringHashMap(u32).init(allocator);
|
var name2user = StringHashMap(u32).init(allocator);
|
||||||
var name2group = StringHashMap(u32).init(allocator);
|
|
||||||
for (users.items(.name)) |name, i| {
|
for (users.items(.name)) |name, i| {
|
||||||
var res1 = try name2user.getOrPut(name);
|
var result = try name2user.getOrPut(name);
|
||||||
if (res1.found_existing)
|
if (result.found_existing)
|
||||||
return error.Duplicate;
|
return error.Duplicate;
|
||||||
res1.value_ptr.* = @intCast(u32, i);
|
result.value_ptr.* = @intCast(u32, i);
|
||||||
|
}
|
||||||
|
// verify whatever comes to cmph are unique: group names
|
||||||
|
var name2group = StringHashMap(u32).init(allocator);
|
||||||
|
for (groups.items(.name)) |name, i| {
|
||||||
|
var result = try name2group.getOrPut(name);
|
||||||
|
if (result.found_existing)
|
||||||
|
return error.Duplicate;
|
||||||
|
result.value_ptr.* = @intCast(u32, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (groups.items(.name)) |name, i| {
|
// verify whatever comes to cmph are unique: gids
|
||||||
var res1 = try name2group.getOrPut(name);
|
{
|
||||||
if (res1.found_existing)
|
const gids = groups.items(.gid);
|
||||||
return error.Duplicate;
|
var last_gid = gids[0];
|
||||||
res1.value_ptr.* = @intCast(u32, i);
|
for (gids[1..]) |gid| {
|
||||||
|
if (gid == last_gid)
|
||||||
|
return err.returnf("duplicate gid {d}", .{gid}, error.Duplicate);
|
||||||
|
last_gid = gid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify whatever comes to cmph are unique: uids
|
||||||
|
{
|
||||||
|
var uid_map = AutoHashMap(u32, void).init(allocator);
|
||||||
|
defer uid_map.deinit();
|
||||||
|
for (users.items(.uid)) |uid| {
|
||||||
|
const result = try uid_map.getOrPut(uid);
|
||||||
|
if (result.found_existing)
|
||||||
|
return err.returnf("duplicate uid {d}", .{uid}, error.Duplicate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var group2users = try allocator.alloc([]u32, groups.len);
|
var group2users = try allocator.alloc([]u32, groups.len);
|
||||||
@ -236,9 +260,9 @@ pub fn testCorpus(allocator: Allocator) !Corpus {
|
|||||||
|
|
||||||
const groups = [_]Group{ group0, group1, group2, group3 };
|
const groups = [_]Group{ group0, group1, group2, group3 };
|
||||||
|
|
||||||
var err_ctx = ErrCtx{};
|
var errc = ErrCtx{};
|
||||||
const result = try Corpus.init(allocator, users[0..], groups[0..], &err_ctx);
|
const result = try Corpus.init(allocator, users[0..], groups[0..], &errc);
|
||||||
try testing.expectEqualStrings("", err_ctx.unwrap().constSlice());
|
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/DB.zig
16
src/DB.zig
@ -10,6 +10,7 @@ const ArrayList = std.ArrayList;
|
|||||||
const AutoHashMap = std.AutoHashMap;
|
const AutoHashMap = std.AutoHashMap;
|
||||||
const BoundedArray = std.BoundedArray;
|
const BoundedArray = std.BoundedArray;
|
||||||
|
|
||||||
|
const ErrCtx = @import("ErrCtx.zig");
|
||||||
const Corpus = @import("Corpus.zig");
|
const Corpus = @import("Corpus.zig");
|
||||||
const pad = @import("padding.zig");
|
const pad = @import("padding.zig");
|
||||||
const compress = @import("compress.zig");
|
const compress = @import("compress.zig");
|
||||||
@ -54,7 +55,10 @@ additional_gids: []const u8,
|
|||||||
pub fn fromCorpus(
|
pub fn fromCorpus(
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
corpus: *const Corpus,
|
corpus: *const Corpus,
|
||||||
|
err: *ErrCtx,
|
||||||
) error{ OutOfMemory, InvalidRecord, TooMany }!DB {
|
) error{ OutOfMemory, InvalidRecord, TooMany }!DB {
|
||||||
|
_ = err;
|
||||||
|
|
||||||
const gids = corpus.groups.items(.gid);
|
const gids = corpus.groups.items(.gid);
|
||||||
const gnames = corpus.groups.items(.name);
|
const gnames = corpus.groups.items(.name);
|
||||||
const uids = corpus.users.items(.uid);
|
const uids = corpus.users.items(.uid);
|
||||||
@ -630,7 +634,8 @@ test "read/write via iovec" {
|
|||||||
var corpus = try Corpus.testCorpus(allocator);
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
|
|
||||||
var db = try DB.fromCorpus(allocator, &corpus);
|
var errc = ErrCtx{};
|
||||||
|
var db = try DB.fromCorpus(allocator, &corpus, &errc);
|
||||||
defer db.deinit(allocator);
|
defer db.deinit(allocator);
|
||||||
|
|
||||||
const fd = try os.memfd_create("test_turbonss_db", 0);
|
const fd = try os.memfd_create("test_turbonss_db", 0);
|
||||||
@ -648,12 +653,14 @@ test "read/write via iovec" {
|
|||||||
|
|
||||||
try testing.expectEqualSlices(u32, db.idx_gid2group, db2.idx_gid2group[0..num_groups]);
|
try testing.expectEqualSlices(u32, db.idx_gid2group, db2.idx_gid2group[0..num_groups]);
|
||||||
try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]);
|
try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]);
|
||||||
|
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getgrnam/getgrgid" {
|
test "getgrnam/getgrgid" {
|
||||||
var corpus = try Corpus.testCorpus(testing.allocator);
|
var corpus = try Corpus.testCorpus(testing.allocator);
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
var db = try DB.fromCorpus(testing.allocator, &corpus);
|
var errc = ErrCtx{};
|
||||||
|
var db = try DB.fromCorpus(testing.allocator, &corpus, &errc);
|
||||||
defer db.deinit(testing.allocator);
|
defer db.deinit(testing.allocator);
|
||||||
var buf = try testing.allocator.alloc(u8, db.getgrBufsize());
|
var buf = try testing.allocator.alloc(u8, db.getgrBufsize());
|
||||||
defer testing.allocator.free(buf);
|
defer testing.allocator.free(buf);
|
||||||
@ -677,6 +684,7 @@ test "getgrnam/getgrgid" {
|
|||||||
try testing.expectEqual(all.gid, 9999);
|
try testing.expectEqual(all.gid, 9999);
|
||||||
try testing.expectEqualStrings(all.name[0..3], "all");
|
try testing.expectEqualStrings(all.name[0..3], "all");
|
||||||
}
|
}
|
||||||
|
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||||
|
|
||||||
_ = try db.getgrnam("all", buf);
|
_ = try db.getgrnam("all", buf);
|
||||||
buf.len -= 1;
|
buf.len -= 1;
|
||||||
@ -686,7 +694,8 @@ test "getgrnam/getgrgid" {
|
|||||||
test "getpwnam/getpwuid" {
|
test "getpwnam/getpwuid" {
|
||||||
var corpus = try Corpus.testCorpus(testing.allocator);
|
var corpus = try Corpus.testCorpus(testing.allocator);
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
var db = try DB.fromCorpus(testing.allocator, &corpus);
|
var errc = ErrCtx{};
|
||||||
|
var db = try DB.fromCorpus(testing.allocator, &corpus, &errc);
|
||||||
defer db.deinit(testing.allocator);
|
defer db.deinit(testing.allocator);
|
||||||
var buf = try testing.allocator.alloc(u8, db.getpwBufsize());
|
var buf = try testing.allocator.alloc(u8, db.getpwBufsize());
|
||||||
defer testing.allocator.free(buf);
|
defer testing.allocator.free(buf);
|
||||||
@ -708,6 +717,7 @@ test "getpwnam/getpwuid" {
|
|||||||
try testing.expectEqual(vidmantas.pw_gid, 128);
|
try testing.expectEqual(vidmantas.pw_gid, 128);
|
||||||
try testing.expectEqualStrings(vidmantas.pw_name[0..10], "vidmantas\x00");
|
try testing.expectEqualStrings(vidmantas.pw_name[0..10], "vidmantas\x00");
|
||||||
}
|
}
|
||||||
|
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||||
|
|
||||||
const long = try db.getpwnam("Name" ** 8, buf);
|
const long = try db.getpwnam("Name" ** 8, buf);
|
||||||
try testing.expectEqualStrings(long.?.pw_name[0..33], "Name" ** 8 ++ "\x00");
|
try testing.expectEqualStrings(long.?.pw_name[0..33], "Name" ** 8 ++ "\x00");
|
||||||
|
@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const Corpus = @import("Corpus.zig");
|
const Corpus = @import("Corpus.zig");
|
||||||
const DB = @import("DB.zig");
|
const DB = @import("DB.zig");
|
||||||
|
const ErrCtx = @import("ErrCtx.zig");
|
||||||
const InvalidHeader = @import("header.zig").Invalid;
|
const InvalidHeader = @import("header.zig").Invalid;
|
||||||
|
|
||||||
const File = @This();
|
const File = @This();
|
||||||
@ -42,11 +43,11 @@ pub const TestDB = struct {
|
|||||||
dir: testing.TmpDir,
|
dir: testing.TmpDir,
|
||||||
path: [:0]const u8,
|
path: [:0]const u8,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator) !TestDB {
|
pub fn init(allocator: Allocator, errc: *ErrCtx) !TestDB {
|
||||||
var corpus = try Corpus.testCorpus(allocator);
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
|
|
||||||
var db = try DB.fromCorpus(allocator, &corpus);
|
var db = try DB.fromCorpus(allocator, &corpus, errc);
|
||||||
defer db.deinit(allocator);
|
defer db.deinit(allocator);
|
||||||
|
|
||||||
var tmp = testing.tmpDir(.{});
|
var tmp = testing.tmpDir(.{});
|
||||||
|
@ -6,6 +6,7 @@ const process = std.process;
|
|||||||
|
|
||||||
const DB = @import("DB.zig");
|
const DB = @import("DB.zig");
|
||||||
const File = @import("File.zig");
|
const File = @import("File.zig");
|
||||||
|
const ErrCtx = @import("ErrCtx.zig");
|
||||||
const CGroup = @import("Group.zig").CGroup;
|
const CGroup = @import("Group.zig").CGroup;
|
||||||
const PackedGroup = @import("PackedGroup.zig");
|
const PackedGroup = @import("PackedGroup.zig");
|
||||||
const CUser = @import("User.zig").CUser;
|
const CUser = @import("User.zig").CUser;
|
||||||
@ -131,7 +132,8 @@ export fn _nss_turbo_getpwuid_r(
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
test "nss_turbo_getpwuid_r" {
|
test "nss_turbo_getpwuid_r" {
|
||||||
var tf = try File.TestDB.init(testing.allocator);
|
var errc = ErrCtx{};
|
||||||
|
var tf = try File.TestDB.init(testing.allocator, &errc);
|
||||||
defer tf.deinit();
|
defer tf.deinit();
|
||||||
|
|
||||||
var env = try process.getEnvMap(testing.allocator);
|
var env = try process.getEnvMap(testing.allocator);
|
||||||
|
@ -97,8 +97,8 @@ fn execute(
|
|||||||
return fail(errc.wrap("init corpus"), stderr, err);
|
return fail(errc.wrap("init corpus"), stderr, err);
|
||||||
|
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
var db = DB.fromCorpus(allocator, &corpus) catch |err|
|
var db = DB.fromCorpus(allocator, &corpus, &errc) catch |err|
|
||||||
return fail(errc.wrap("construct db from corpus"), stderr, err);
|
return fail(errc.wrap("construct DB from corpus"), stderr, err);
|
||||||
defer db.deinit(allocator);
|
defer db.deinit(allocator);
|
||||||
|
|
||||||
const fd = os.open(outFile, os.O.WRONLY | os.O.TRUNC | os.O.CREAT, 0644) catch |err|
|
const fd = os.open(outFile, os.O.WRONLY | os.O.TRUNC | os.O.CREAT, 0644) catch |err|
|
||||||
|
Loading…
Reference in New Issue
Block a user