Skip to content

Commit 653f572

Browse files
MagicalTuxclaude
andcommitted
feat: implement writer TODOs for file type support
Implemented remaining TODOs in writer: 1. Extract uid/gid from info.Sys() if available - Check for Uid()/Gid() methods on Sys() interface - Capture uid/gid for proper ownership in archive 2. Read symlink targets using fs.ReadLink - Add symTarget field to writerInode - Read and store symlink target path during Add() - Serialize symlink data in serializeInode() 3. Handle all file types (char, block, fifo, socket) - Add proper type detection for CharDevType, BlockDevType, FifoType, SocketType - Implement serialization for device nodes (with rdev=0 for now) - Implement serialization for named pipes and sockets 4. Document fragment and export table status - Set fragTableStart to 0xFFFFFFFFFFFFFFFF (no fragments) - Set exportTableStart to 0xFFFFFFFFFFFFFFFF (no export table) All 21 tests continue to pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent da86e91 commit 653f572

1 file changed

Lines changed: 70 additions & 13 deletions

File tree

‎writer.go‎

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@ type writerInode struct {
5959
ino uint32
6060

6161
// File metadata
62-
mode fs.FileMode
63-
size uint64
64-
modTime int64
65-
uid uint32
66-
gid uint32
67-
nlink uint32
68-
fileType Type
62+
mode fs.FileMode
63+
size uint64
64+
modTime int64
65+
uid uint32
66+
gid uint32
67+
nlink uint32
68+
fileType Type
69+
symTarget string // symlink target path
6970

7071
// Source filesystem for reading file data
7172
srcFS fs.FS
@@ -220,7 +221,16 @@ func (w *Writer) Add(path string, d fs.DirEntry, err error) error {
220221
srcFS: w.srcFS, // Capture current source filesystem
221222
}
222223

223-
// TODO: Extract uid/gid from info.Sys() if available
224+
// Extract uid/gid from info.Sys() if available
225+
if sys := info.Sys(); sys != nil {
226+
if statT, ok := sys.(interface {
227+
Uid() uint32
228+
Gid() uint32
229+
}); ok {
230+
inode.uid = statT.Uid()
231+
inode.gid = statT.Gid()
232+
}
233+
}
224234

225235
// Determine inode type
226236
switch {
@@ -232,10 +242,26 @@ func (w *Writer) Add(path string, d fs.DirEntry, err error) error {
232242
inode.fileType = FileType
233243
case info.Mode()&fs.ModeSymlink != 0:
234244
inode.fileType = SymlinkType
235-
// TODO: Read symlink target
245+
// Read symlink target
246+
if inode.srcFS != nil {
247+
target, err := fs.ReadLink(inode.srcFS, path)
248+
if err != nil {
249+
return fmt.Errorf("failed to read symlink %s: %w", path, err)
250+
}
251+
inode.symTarget = target
252+
inode.size = uint64(len(target))
253+
}
254+
case info.Mode()&fs.ModeCharDevice != 0:
255+
inode.fileType = CharDevType
256+
case info.Mode()&fs.ModeDevice != 0:
257+
inode.fileType = BlockDevType
258+
case info.Mode()&fs.ModeNamedPipe != 0:
259+
inode.fileType = FifoType
260+
case info.Mode()&fs.ModeSocket != 0:
261+
inode.fileType = SocketType
236262
default:
237-
// TODO: Handle other file types (char, block, fifo, socket)
238-
inode.fileType = FileType // treat as regular file for now
263+
// Unknown type, treat as regular file
264+
inode.fileType = FileType
239265
}
240266

241267
// Add to inode list and map
@@ -507,6 +533,34 @@ func (w *Writer) serializeInode(ino *writerInode) ([]byte, error) {
507533
return nil, err
508534
}
509535
}
536+
case SymlinkType: // Basic Symlink
537+
// nlink
538+
if err := writeBinary(buf, order, ino.nlink); err != nil {
539+
return nil, err
540+
}
541+
// symlink_size - length of target path
542+
if err := writeBinary(buf, order, uint32(len(ino.symTarget))); err != nil {
543+
return nil, err
544+
}
545+
// symlink - target path
546+
if err := writeBinary(buf, order, []byte(ino.symTarget)); err != nil {
547+
return nil, err
548+
}
549+
case CharDevType, BlockDevType: // Device nodes
550+
// nlink
551+
if err := writeBinary(buf, order, ino.nlink); err != nil {
552+
return nil, err
553+
}
554+
// rdev - device number (major/minor)
555+
// For now, write 0 as we don't extract device numbers from source
556+
if err := writeBinary(buf, order, uint32(0)); err != nil {
557+
return nil, err
558+
}
559+
case FifoType, SocketType: // Named pipes and sockets
560+
// nlink
561+
if err := writeBinary(buf, order, ino.nlink); err != nil {
562+
return nil, err
563+
}
510564
default:
511565
return nil, fmt.Errorf("unsupported inode type %d", ino.fileType)
512566
}
@@ -1181,8 +1235,11 @@ func (w *Writer) Finalize() error {
11811235
return err
11821236
}
11831237

1184-
// TODO: Write fragment table (can be empty)
1185-
// TODO: Write export table (can be empty)
1238+
// Write fragment table (empty for now - no fragment support yet)
1239+
w.fragTableStart = 0xFFFFFFFFFFFFFFFF // No fragments
1240+
1241+
// Write export table (empty for now - not required for basic functionality)
1242+
w.exportTableStart = 0xFFFFFFFFFFFFFFFF // No export table
11861243

11871244
w.bytesUsed = w.offset
11881245

0 commit comments

Comments
 (0)