diff --git a/src/browser.zig b/src/browser.zig
index dac093b3f766e2ee9707d932b15d82f9ae505cdf..e5de3a7c42de5612913d5d68e3f4d9e7af534a2f 100644
--- a/src/browser.zig
+++ b/src/browser.zig
@@ -180,7 +180,7 @@ const Row = struct {
     fn size(self: *Self) void {
         var width = if (main.config.si) @as(u32, 9) else 10;
         if (dir_has_shared and main.config.show_shared != .off)
-            width += 1 + width;
+            width += 2 + width;
         defer self.col += width;
         const item = self.item orelse return;
         const siz = if (main.config.show_blocks) blocksToSize(item.blocks) else item.size;
@@ -191,7 +191,7 @@ const Row = struct {
         ui.addsize(self.bg, siz);
         if (shr > 0 and main.config.show_shared != .off) {
             self.bg.fg(.flag);
-            ui.addstr(if (main.config.show_shared == .unique) " U" else " S");
+            ui.addstr(if (main.config.show_shared == .unique) " U " else " S ");
             ui.addsize(self.bg, shr);
         }
     }
diff --git a/src/scan.zig b/src/scan.zig
index c15933078e5ad620de95ad13c970b466597c8aff..5a5377c71a5652325663c62fb1df951c1efa0a92 100644
--- a/src/scan.zig
+++ b/src/scan.zig
@@ -410,7 +410,12 @@ pub fn scanRoot(path: []const u8, out: ?std.fs.File) !void {
 // tests can be written.
 const Import = struct {
     ctx: Context,
-    rd: std.io.BufferedReader(4096, std.fs.File.Reader),
+
+    rd: std.fs.File,
+    rdoff: usize = 0,
+    rdsize: usize = 0,
+    rdbuf: [8*1024]u8 = undefined,
+
     ch: u8 = 0, // last read character, 0 = EOF (or invalid null byte, who cares)
     byte: u64 = 1,
     line: u64 = 1,
@@ -424,17 +429,21 @@ const Import = struct {
 
     // Advance to the next byte, sets ch.
     fn con(self: *Self) void {
-        // XXX: This indirection through a BufferedReader to just read 1 byte
-        // at a time may have some extra overhead. Wrapping our own LinearFifo
-        // may or may not be worth it, needs benchmarking.
-        self.ch = self.rd.reader().readByte() catch |e| switch (e) {
-            error.EndOfStream => 0,
-            error.InputOutput => self.die("I/O error"),
-            error.IsDir => self.die("not a file"), // should be detected at open() time, but no flag for that...
-            // TODO: This one can be retried
-            error.SystemResources => self.die("out of memory"),
-            else => unreachable,
-        };
+        if (self.rdoff >= self.rdsize) {
+            self.rdoff = 0;
+            self.rdsize = self.rd.read(&self.rdbuf) catch |e| switch (e) {
+                error.InputOutput => self.die("I/O error"),
+                error.IsDir => self.die("not a file"), // should be detected at open() time, but no flag for that...
+                error.SystemResources => self.die("out of memory"),
+                else => unreachable,
+            };
+            if (self.rdsize == 0) {
+                self.ch = 0;
+                return;
+            }
+        }
+        self.ch = self.rdbuf[self.rdoff];
+        self.rdoff += 1;
         self.byte += 1;
     }
 
@@ -472,7 +481,6 @@ const Import = struct {
     // Any characters beyond the size of the buffer are consumed but otherwise discarded.
     // (May store fewer characters in the case of \u escapes, it's not super precise)
     fn string(self: *Self, buf: []u8) []u8 {
-        std.debug.assert(self.ch == '"');
         if (self.next() != '"') self.die("expected '\"'");
         var n: u64 = 0;
         while (true) {
@@ -788,7 +796,7 @@ pub fn importRoot(path: [:0]const u8, out: ?std.fs.File) void {
 
     var imp = Import{
         .ctx = if (out) |f| Context.initFile(f) else Context.initMem(),
-        .rd = std.io.bufferedReader(fd.reader()),
+        .rd = fd,
     };
     active_context = &imp.ctx;
     defer active_context = null;