DF-2756 / dirread.c
/* DF-2756: read() on a directory fd -> raw on-disk directory blocks (UFS) */ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <errno.h> int main(int argc, char **argv) { const char *path = argc > 1 ? argv[1] : "/boot"; int fd = open(path, O_RDONLY); if (fd < 0) { perror("open"); return 1; } char buf[65536]; ssize_t n = read(fd, buf, sizeof(buf)); printf("read(%s) = %zd errno=%d\n", path, n, n < 0 ? errno : 0); if (n > 0) { /* dump first 2 dirent slots raw */ unsigned char *p = (unsigned char*)buf; for (int i = 0; i < 4 && (i+1)*16 <= n; i++) { printf("dirent[%d] raw 16 bytes:", i); for (int j = 0; j < 16; j++) printf(" %02x", p[i*16+j]); printf("\n"); } /* parse UFS dirents: u_char d_type; u_char d_namlen; u_short d_reclen; */ long off = 0; int cnt = 0; while (off + 8 <= n && cnt < 12) { unsigned char *d = (unsigned char*)buf + off; unsigned short reclen = d[2] | (d[3] << 8); unsigned char namlen = d[1]; if (reclen < 8 || off + reclen > n) { printf("bad reclen %u at %ld\n", reclen, off); break; } char name[256]; int cp = namlen < 255 ? namlen : 255; memcpy(name, d+8, cp); name[cp] = 0; printf("dirent off=%ld reclen=%u namlen=%u name='%s'\n", off, reclen, namlen, name); /* slack bytes between name end and next entry */ int used = 8 + ((cp + 1 + 3) & ~3); if (reclen > used && reclen - used >= 4) { printf(" slack (%d bytes):", reclen - used); for (int j = used; j < reclen && j < used + 24; j++) printf(" %02x", d[j]); printf("\n"); } off += reclen; cnt++; } } close(fd); return 0; } |