| import { motion } from 'motion/react'; |
| export default function FileSystemDiagram() { |
| return ( |
| <motion.div initial={{ opacity: 0, y: 24, scale: 0.97 }} animate={{ opacity: 1, y: 0, scale: 1 }} transition={{ duration: 0.7, ease: [0.25,0.1,0.25,1] as const, delay: 0.2 }} className="mt-10 mb-4"> |
| <div className="text-center mb-6"><span className="text-lg font-bold uppercase tracking-widest text-violet-400" style={{ filter: 'drop-shadow(0 0 10px rgba(139,92,246,0.5))' }}>FILE SYSTEMS</span></div> |
| <svg viewBox="0 0 900 640" className="w-full max-w-6xl mx-auto" style={{ filter: 'drop-shadow(0 0 30px rgba(139,92,246,0.1))' }}> |
| <defs> |
| <marker id="fsArr" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#a855f7"/></marker> |
| <linearGradient id="fsHdr" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stopColor="rgba(139,92,246,0.2)"/><stop offset="100%" stopColor="rgba(139,92,246,0.05)"/></linearGradient> |
| </defs> |
| <rect x="20" y="10" width="860" height="44" rx="12" fill="url(#fsHdr)" stroke="rgba(139,92,246,0.4)" strokeWidth="2"/> |
| <text x="45" y="28" fill="#c084fc" fontSize="10" fontWeight="700" fontFamily="'Inter',sans-serif">File System:</text> |
| <text x="145" y="28" fill="#d8b4fe" fontSize="9" fontFamily="'Inter',sans-serif">The OS's method of organizing, storing, naming, and retrieving data on storage devices.</text> |
| <text x="45" y="42" fill="#64748b" fontSize="8" fontFamily="'Inter',sans-serif">Examples: ext4 (Linux), NTFS (Windows), APFS (macOS), FAT32, ZFS, Btrfs</text> |
| |
| {/* Directory Tree */} |
| <rect x="20" y="65" width="340" height="310" rx="12" fill="rgba(59,130,246,0.05)" stroke="rgba(59,130,246,0.35)" strokeWidth="1.5"/> |
| <text x="190" y="83" textAnchor="middle" fill="#60a5fa" fontSize="10" fontWeight="800" fontFamily="'Inter',sans-serif">DIRECTORY STRUCTURE</text> |
| <text x="30" y="98" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Hierarchical tree. Every file has a full path from root.</text> |
| {/* Tree viz */} |
| <text x="180" y="118" textAnchor="middle" fill="#fbbf24" fontSize="9" fontWeight="700" fontFamily="'Inter',sans-serif">/ (root)</text> |
| <line x1="180" y1="122" x2="100" y2="140" stroke="rgba(59,130,246,0.4)" strokeWidth="1.2"/> |
| <line x1="180" y1="122" x2="260" y2="140" stroke="rgba(59,130,246,0.4)" strokeWidth="1.2"/> |
| <text x="90" y="153" textAnchor="middle" fill="#60a5fa" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">π home</text> |
| <text x="260" y="153" textAnchor="middle" fill="#60a5fa" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">π etc</text> |
| <line x1="90" y1="157" x2="60" y2="175" stroke="rgba(59,130,246,0.35)" strokeWidth="1"/> |
| <line x1="90" y1="157" x2="120" y2="175" stroke="rgba(59,130,246,0.35)" strokeWidth="1"/> |
| <text x="50" y="188" textAnchor="middle" fill="#c084fc" fontSize="7.5" fontFamily="'Inter',sans-serif">π user1</text> |
| <text x="120" y="188" textAnchor="middle" fill="#c084fc" fontSize="7.5" fontFamily="'Inter',sans-serif">π user2</text> |
| <line x1="50" y1="192" x2="30" y2="210" stroke="rgba(168,85,247,0.3)" strokeWidth="1"/> |
| <line x1="50" y1="192" x2="70" y2="210" stroke="rgba(168,85,247,0.3)" strokeWidth="1"/> |
| <text x="30" y="222" textAnchor="middle" fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">π notes.txt</text> |
| <text x="70" y="222" textAnchor="middle" fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">π docs</text> |
| <line x1="70" y1="226" x2="70" y2="240" stroke="rgba(168,85,247,0.25)" strokeWidth="1"/> |
| <text x="70" y="252" textAnchor="middle" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">π resume.pdf</text> |
| <text x="30" y="280" fill="#60a5fa" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Path types:</text> |
| <text x="30" y="293" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Absolute: /home/user1/docs/resume.pdf</text> |
| <text x="30" y="306" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Relative: ../docs/resume.pdf (from user2)</text> |
| <text x="30" y="322" fill="#60a5fa" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Special entries:</text> |
| <text x="30" y="335" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">. = current directory | .. = parent directory</text> |
| <text x="30" y="349" fill="#fbbf24" fontSize="7.5" fontFamily="'Inter',sans-serif">Hard link: same inode, different directory entry</text> |
| <text x="30" y="362" fill="#fbbf24" fontSize="7.5" fontFamily="'Inter',sans-serif">Soft link (symlink): pointer to another file path</text> |
| |
| {/* Inode */} |
| <rect x="375" y="65" width="505" height="310" rx="12" fill="rgba(245,158,11,0.05)" stroke="rgba(245,158,11,0.35)" strokeWidth="1.5"/> |
| <text x="627" y="83" textAnchor="middle" fill="#fbbf24" fontSize="10" fontWeight="800" fontFamily="'Inter',sans-serif">INODE STRUCTURE (Linux ext4)</text> |
| <text x="385" y="98" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Every file has an inode containing metadata. Directory entry maps filename β inode number.</text> |
| {/* Inode box */} |
| <rect x="385" y="106" width="220" height="240" rx="8" fill="rgba(245,158,11,0.08)" stroke="rgba(245,158,11,0.3)" strokeWidth="1.5"/> |
| <text x="495" y="122" textAnchor="middle" fill="#fbbf24" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">INODE #{'\u00A0'}1234</text> |
| {[ |
| {field:'File type',val:'Regular file / dir / link'}, |
| {field:'Permissions',val:'rwxr-xr-- (owner/grp/other)'}, |
| {field:'Owner UID/GID',val:'1000 / 1000'}, |
| {field:'File size',val:'4,096 bytes'}, |
| {field:'Link count',val:'2 (hard links)'}, |
| {field:'atime',val:'Last accessed'}, |
| {field:'mtime',val:'Last modified'}, |
| {field:'ctime',val:'Last changed (inode)'}, |
| {field:'Data block ptrs',val:'12 direct + indirect'}, |
| ].map(({field,val},i)=>( |
| <g key={i}> |
| <rect x="390" y={128+i*23} width="210" height="20" rx="2" fill={i%2===0?'rgba(245,158,11,0.05)':'rgba(245,158,11,0.02)'}/> |
| <text x="396" y={141+i*23} fill="#fbbf24" fontSize="7" fontWeight="700" fontFamily="'Inter',sans-serif">{field}</text> |
| <text x="480" y={141+i*23} fill="#94a3b8" fontSize="6.5" fontFamily="'Inter',sans-serif">{val}</text> |
| </g> |
| ))} |
| {/* Data block layout */} |
| <text x="620" y="122" fill="#fbbf24" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Data Block Addressing:</text> |
| <text x="620" y="136" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">12 direct pointers β data blocks</text> |
| <text x="620" y="149" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">1 single indirect β block of pointers</text> |
| <text x="620" y="162" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">1 double indirect β 2 levels of ptrs</text> |
| <text x="620" y="175" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">1 triple indirect β 3 levels of ptrs</text> |
| {/* Block diagram */} |
| <rect x="620" y="185" width="50" height="30" rx="4" fill="rgba(245,158,11,0.15)" stroke="rgba(245,158,11,0.4)" strokeWidth="1"/> |
| <text x="645" y="204" textAnchor="middle" fill="#fbbf24" fontSize="6.5" fontFamily="'Inter',sans-serif">Inode</text> |
| {[0,1,2].map(i=>( |
| <g key={i}> |
| <line x1="670" y1={195+i*10} x2="700" y2={195+i*10} stroke="rgba(245,158,11,0.4)" strokeWidth="1" markerEnd="url(#fsArr)"/> |
| <rect x="700" y={190+i*10} width="40" height="8" rx="2" fill="rgba(245,158,11,0.1)" stroke="rgba(245,158,11,0.3)" strokeWidth="0.5"/> |
| <text x="720" y={197+i*10} textAnchor="middle" fill="#94a3b8" fontSize="5.5" fontFamily="'Inter',sans-serif">Data{i+1}</text> |
| </g> |
| ))} |
| <line x1="670" y1="215" x2="700" y2="240" stroke="rgba(59,130,246,0.4)" strokeWidth="1" markerEnd="url(#fsArr)"/> |
| <rect x="700" y="236" width="50" height="16" rx="3" fill="rgba(59,130,246,0.1)" stroke="rgba(59,130,246,0.3)" strokeWidth="1"/> |
| <text x="725" y="247" textAnchor="middle" fill="#60a5fa" fontSize="6" fontFamily="'Inter',sans-serif">Indirect Block</text> |
| <text x="620" y="278" fill="#fbbf24" fontSize="7.5" fontWeight="700" fontFamily="'Inter',sans-serif">Key insight:</text> |
| <text x="620" y="291" fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">Filename NOT stored in inode.</text> |
| <text x="620" y="303" fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">Directory entry maps name β inode#.</text> |
| <text x="620" y="316" fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">Multiple names β same inode = hard links.</text> |
| <text x="620" y="332" fill="#4ade80" fontSize="7.5" fontFamily="'Inter',sans-serif">Deleting file = unlink (decrement count).</text> |
| <text x="620" y="344" fill="#4ade80" fontSize="7.5" fontFamily="'Inter',sans-serif">Data freed when link count hits 0.</text> |
| <text x="620" y="358" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">ls -i shows inode numbers.</text> |
| |
| {/* Allocation methods + FS types */} |
| <rect x="20" y="388" width="420" height="230" rx="12" fill="rgba(168,85,247,0.05)" stroke="rgba(168,85,247,0.3)" strokeWidth="1.5"/> |
| <text x="230" y="406" textAnchor="middle" fill="#c084fc" fontSize="10" fontWeight="800" fontFamily="'Inter',sans-serif">FILE ALLOCATION METHODS</text> |
| {[ |
| {m:'Contiguous',d:'File blocks stored consecutively. Fast sequential access. Suffers external fragmentation. Used in CD-ROM.',c:'#fbbf24',pros:'Fast reads',cons:'External frag'}, |
| {m:'Linked List',d:'Each block has pointer to next block. No fragmentation. Slow random access (must traverse links).',c:'#60a5fa',pros:'No ext frag',cons:'Slow random access'}, |
| {m:'Indexed (FAT/Inode)',d:'Index block holds all data block pointers. Supports direct + indirect addressing. Used in ext4.',c:'#4ade80',pros:'Fast random access',cons:'Index block overhead'}, |
| ].map(({m,d,c,pros,cons},i)=>( |
| <g key={i}> |
| <rect x="25" y={415+i*65} width="405" height="58" rx="7" fill={`${c}06`} stroke={`${c}25`} strokeWidth="1"/> |
| <text x="32" y={431+i*65} fill={c} fontSize="9" fontWeight="700" fontFamily="'Inter',sans-serif">{m}</text> |
| <text x="32" y={444+i*65} fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">{d.slice(0,60)}</text> |
| <text x="32" y={455+i*65} fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">{d.slice(60)}</text> |
| <text x="32" y={467+i*65} fill="#4ade80" fontSize="7" fontFamily="'Inter',sans-serif">β {pros}</text> |
| <text x="130" y={467+i*65} fill="#f87171" fontSize="7" fontFamily="'Inter',sans-serif">β {cons}</text> |
| </g> |
| ))} |
| |
| <rect x="460" y="388" width="420" height="230" rx="12" fill="rgba(34,197,94,0.04)" stroke="rgba(34,197,94,0.3)" strokeWidth="1.5"/> |
| <text x="670" y="406" textAnchor="middle" fill="#4ade80" fontSize="10" fontWeight="800" fontFamily="'Inter',sans-serif">FILE SYSTEM TYPES COMPARISON</text> |
| <rect x="465" y="412" width="410" height="14" rx="3" fill="rgba(34,197,94,0.15)"/> |
| {['FS','OS','Max File','Journal','Features'].map((h,i)=><text key={i} x={[470,520,575,640,700][i]} y="422" fill="#4ade80" fontSize="7" fontWeight="700" fontFamily="'Inter',sans-serif">{h}</text>)} |
| {[ |
| {fs:'ext4',os:'Linux',max:'16TB',j:'Yes',feat:'Most common Linux FS',c:'#4ade80'}, |
| {fs:'NTFS',os:'Windows',max:'16EB',j:'Yes',feat:'ACLs, encryption, compression',c:'#60a5fa'}, |
| {fs:'APFS',os:'macOS',max:'8EB',j:'CoW',feat:'Snapshots, clones, SSD-opt',c:'#94a3b8'}, |
| {fs:'FAT32',os:'Universal',max:'4GB',j:'No',feat:'Wide compatibility, USB drives',c:'#fbbf24'}, |
| {fs:'ZFS',os:'Linux/BSD',max:'256ZB',j:'CoW',feat:'Snapshots, RAID, self-healing',c:'#c084fc'}, |
| {fs:'Btrfs',os:'Linux',max:'16EB',j:'CoW',feat:'Snapshots, compression, RAID',c:'#f97316'}, |
| ].map(({fs,os,max,j,feat,c},i)=>( |
| <g key={i}> |
| <rect x="465" y={427+i*27} width="410" height="25" rx="2" fill={i%2===0?'rgba(255,255,255,0.01)':'rgba(255,255,255,0.025)'}/> |
| <text x="470" y={443+i*27} fill={c} fontSize="7.5" fontWeight="700" fontFamily="'Inter',sans-serif">{fs}</text> |
| <text x="520" y={443+i*27} fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">{os}</text> |
| <text x="575" y={443+i*27} fill="#e2e8f0" fontSize="7" fontFamily="'Inter',sans-serif">{max}</text> |
| <text x="640" y={443+i*27} fill={j==='Yes'?'#4ade80':j==='CoW'?'#fbbf24':'#f87171'} fontSize="7" fontFamily="'Inter',sans-serif">{j}</text> |
| <text x="700" y={443+i*27} fill="#64748b" fontSize="6.5" fontFamily="'Inter',sans-serif">{feat}</text> |
| </g> |
| ))} |
| <text x="465" y="596" fill="#fbbf24" fontSize="7.5" fontFamily="'Inter',sans-serif">Journaling: logs changes before writing β fast crash recovery. CoW (Copy-on-Write): safer, enables snapshots.</text> |
| <text x="465" y="610" fill="#4ade80" fontSize="7.5" fontFamily="'Inter',sans-serif">Virtual FS (VFS): Linux abstraction layer β same API for all FS types (ext4, NTFS, NFS, procfs, etc.)</text> |
| </svg> |
| </motion.div> |
| ); |
| } |
|
|