diff --git a/cli/src/utils.zig b/cli/src/utils.zig index 274dd2b..1408f23 100644 --- a/cli/src/utils.zig +++ b/cli/src/utils.zig @@ -3,6 +3,7 @@ pub const auth = @import("utils/auth.zig"); pub const colors = @import("utils/colors.zig"); pub const crypto = @import("utils/crypto.zig"); pub const flags = @import("utils/flags.zig"); +pub const hash = @import("utils/hash.zig"); pub const history = @import("utils/history.zig"); pub const io = @import("utils/io.zig"); pub const json = @import("utils/json.zig"); diff --git a/cli/src/utils/hash.zig b/cli/src/utils/hash.zig index 6825169..6d12e27 100644 --- a/cli/src/utils/hash.zig +++ b/cli/src/utils/hash.zig @@ -66,8 +66,7 @@ pub const DatasetHash = struct { : [eax] "+r" (eax), [ebx] "=r" (ebx), : [ecx] "r" (ecx), - : .{ .edx = true, .memory = true } - ); + : .{ .edx = true, .memory = true }); // Bit 29 of EBX indicates SHA-NI support return (ebx & (1 << 29)) != 0; @@ -279,7 +278,7 @@ pub const DatasetHash = struct { }; /// Security: validate path for traversal attacks -fn validatePath(path: []const u8) !void { +pub fn validatePath(path: []const u8) !void { // Check for path traversal attempts if (std.mem.indexOf(u8, path, "..") != null) { // Only allow ".." at start or after "/" diff --git a/cli/tests/hash_test.zig b/cli/tests/hash_test.zig index 9cb688f..f0fa8c9 100644 --- a/cli/tests/hash_test.zig +++ b/cli/tests/hash_test.zig @@ -1,21 +1,31 @@ const std = @import("std"); -const hash = @import("../src/utils/hash.zig"); +const src = @import("src"); +const hash = src.utils.hash; test "hash single file" { const allocator = std.testing.allocator; // Create a temporary file - const tmp_dir = std.testing.tmpDir(.{}); + var tmp_dir = std.testing.tmpDir(.{}); defer tmp_dir.cleanup(); const test_content = "hello world"; - try tmp_dir.dir.writeFile("test.txt", test_content); + try tmp_dir.dir.writeFile(.{ + .sub_path = "test.txt", + .data = test_content, + }); + + // Get the temp directory path + var path_buf: [4096]u8 = undefined; + const tmp_path = try tmp_dir.dir.realpath(".", &path_buf); + const file_path = try std.fs.path.join(allocator, &[_][]const u8{ tmp_path, "test.txt" }); + defer allocator.free(file_path); // Hash the file var hasher = try hash.DatasetHash.init(allocator, 0); defer hasher.deinit(); - const file_hash = try hasher.hashFile("test.txt"); + const file_hash = try hasher.hashFile(file_path); try std.testing.expectEqual(@as(usize, 64), file_hash.len); } @@ -23,15 +33,24 @@ test "hash empty file" { const allocator = std.testing.allocator; // Create a temporary empty file - const tmp_dir = std.testing.tmpDir(.{}); + var tmp_dir = std.testing.tmpDir(.{}); defer tmp_dir.cleanup(); - try tmp_dir.dir.writeFile("empty.txt", ""); + try tmp_dir.dir.writeFile(.{ + .sub_path = "empty.txt", + .data = "", + }); + + // Get the temp directory path + var path_buf: [4096]u8 = undefined; + const tmp_path = try tmp_dir.dir.realpath(".", &path_buf); + const file_path = try std.fs.path.join(allocator, &[_][]const u8{ tmp_path, "empty.txt" }); + defer allocator.free(file_path); var hasher = try hash.DatasetHash.init(allocator, 0); defer hasher.deinit(); - const file_hash = try hasher.hashFile("empty.txt"); + const file_hash = try hasher.hashFile(file_path); try std.testing.expectEqual(@as(usize, 64), file_hash.len); }