const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; const print = std.debug.print; const c = @cImport({ @cInclude("errno.h"); @cInclude("stdio.h"); if (@import("builtin").os.tag != .windows) { @cInclude("sys/statvfs.h"); } }); const paths = @import("../paths.zig"); const formatDosPath = paths.formatDosPath; const convertTo83 = paths.convertTo83; const types = @import("./types.zig"); const CommandStatus = types.CommandStatus; const OutputCapture = types.OutputCapture; const InputSource = types.InputSource; fn formatDosDateTime(allocator: Allocator, timestamp_secs: i64) ![]const u8 { const epoch_seconds = @as(u64, @intCast(@max(timestamp_secs, 0))); const epoch_day = @divFloor(epoch_seconds, std.time.s_per_day); const day_seconds = epoch_seconds % std.time.s_per_day; // Calculate date (simplified) var year: u32 = 1970; // Start from Unix epoch year var remaining_days = epoch_day; // Simple year calculation while (remaining_days >= 365) { const days_in_year: u64 = if (isLeapYear(year)) 366 else 365; if (remaining_days < days_in_year) break; remaining_days -= days_in_year; year += 1; } // Simple month/day calculation (approximate) const month = @min(@divFloor(remaining_days, 30) + 1, 12); const day = @min(remaining_days % 30 + 1, 31); // Calculate time const hours = day_seconds / std.time.s_per_hour; const minutes = (day_seconds % std.time.s_per_hour) / std.time.s_per_min; // Format as MM-DD-YY HH:MMa (DOS style) const am_pm = if (hours < 12) "a" else "p"; const display_hour = if (hours == 0) 12 else if (hours > 12) hours - 12 else hours; return try std.fmt.allocPrint(allocator, "{d:0>2}-{d:0>2}-{d:0>2} {d:>2}:{d:0>2}{s}", .{ @as(u32, @intCast(month)), @as(u32, @intCast(day)), @as(u32, @intCast(year % 100)), @as(u32, @intCast(display_hour)), @as(u32, @intCast(minutes)), am_pm }); } fn isLeapYear(year: u32) bool { return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0); } const GetFreeDiskSpaceError = error{ NotImplemented, AccessDenied }; fn getFreeDiskSpace(path: []const u8) GetFreeDiskSpaceError!u64 { if (@import("builtin").os.tag == .windows) { return error.NotImplemented; } var stat: c.struct_statvfs = undefined; if (c.statvfs(path.ptr, &stat) != 0) { _ = c.perror("statvfs"); return error.AccessDenied; } return stat.f_bsize * stat.f_bfree; } pub const Dir = struct { path: []const u8, pub fn eval(dir: Dir, allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource) !CommandStatus { _ = input_source; var output_buffer = ArrayList(u8).init(allocator); defer output_buffer.deinit(); // Format path in DOS style with backslashes and uppercase drive letter const formatted_path = try formatDosPath(allocator, dir.path); defer allocator.free(formatted_path); // Get volume label (simplified - just show drive) const drive_letter = if (formatted_path.len >= 2 and formatted_path[1] == ':') formatted_path[0] else 'C'; try output_buffer.writer().print(" Volume in drive {c} has no label\n", .{drive_letter}); try output_buffer.writer().print(" Volume Serial Number is 1234-5678\n", .{}); try output_buffer.writer().print("\n Directory of {s}\n\n", .{formatted_path}); var dir_iterator = std.fs.cwd().openDir(dir.path, .{ .iterate = true }) catch { const error_msg = "File not found\n"; if (output_capture) |capture| { try capture.write(error_msg); } else { print("{s}", .{error_msg}); } return CommandStatus{ .Code = 1 }; }; defer dir_iterator.close(); var iterator = dir_iterator.iterate(); var file_count: u32 = 0; var dir_count: u32 = 0; var total_file_bytes: u64 = 0; while (try iterator.next()) |entry| { const stat = dir_iterator.statFile(entry.name) catch continue; // Convert timestamp to DOS date/time format const mtime_secs = @divFloor(stat.mtime, std.time.ns_per_s); const date_time = try formatDosDateTime(allocator, @intCast(mtime_secs)); defer allocator.free(date_time); // Convert filename to 8.3 format const short_name = try convertTo83(allocator, entry.name); defer allocator.free(short_name); switch (entry.kind) { .directory => { try output_buffer.writer().print("{s}