posts for: #development

automated git commits

overview

a tool for devs who want to streamline their git workflow. it uses the groq api to auto-generate commit messages based on your staged changes by tracking your git diff.​

how it works

the prepare-commit-msg hook taps into your git process and crafts a commit message using an llm. you can apply this hook across multiple repos using the update_hooks.sh script. just set your GROQ_API_KEY as an environment variable.

[read more]

file system

overview

a c-based implementation of a simplified file system. it mimics a windows-style FAT (file allocation table) architecture and supports core file ops like creating, reading, writing, deleting, and managing file descriptors. the project simulates a virtual disk environment for testing too.

implementation

several key components:

  • superblock: holds metadata about the file system layout, including directory and FAT sizes, and the starting block of data.
  • directory: a statically allocated array that can hold up to 64 files, each entry storing file metadata like name, size, existence flag, reference count, and starting block.
  • FAT: an array of 8192 integers representing the file allocation table, where each entry points to the next block in a file or indicates the end of a file.
  • file descriptor table: manages open files with entries containing an offset, a usage flag, and an index linking to the directory.
  • fs_buffer: a fixed-size buffer (4096 bytes) used for file system operations.

core functions

  • make_fs(): initializes the virtual disk, sets up the superblock, FAT, and directory, and writes them to disk.
  • mount_fs(): loads the file system from disk into memory, reading the superblock, FAT, and directory.
  • umount_fs(): writes the in-memory structures back to disk and closes the virtual disk.
  • fs_create(): creates a new file, ensuring the name is valid and not already in use, and allocates a starting block in the FAT.
  • fs_open(): opens an existing file by finding an available file descriptor and updating the reference count.
  • fs_close(): closes an open file descriptor and decrements the corresponding reference count.
  • fs_write() / fs_read(): handles writing to and reading from files, managing offsets and traversing the FAT as needed.
  • fs_delete(): removes a file by clearing its directory entry and freeing its blocks in the FAT.

future

definitely room for adding concurrent access controls.

[read more]

pthreads library

overview

this repo is a custom threading library built in c, designed to mimic core pthread functionality from scratch. it reimplements threading primitives like pthread_create, pthread_join, and pthread_exit, along with basic semaphore support. this project definitely helped me explore how user-level threading and synchronization can be manually orchestrated in a unix-like environment.

architecture

the core of the system revolves around a thread control block (TCB) array that can manage up to 128 threads. each TCB stores metadata like thread id, execution status (ready, running, blocked, exited), a jmp_buf for context switching, and a pointer to its allocated stack. there is also a global variable tracks the currently running thread and a signal-based timer (sigalrm) triggers context switches every 50ms via a scheduler function.

[read more]

shell

overview

a custom-built shell written in c. replicates the core functionality of a unix shell, supporting features like command execution, piping, file redirection, and background process management. helped me understand how shells work under the hood.

features

  • command execution: runs both built-in and external commands.
  • piping: allows the output of one command to be used as the input for another.
  • file redirection: supports input (<) and output (>) redirection.
  • background processes: enables commands to run in the background using &.

implementation

the shell uses system calls like fork(), exec(), and wait() to manage processes. it parses user input to identify commands, arguments, and special characters for piping or redirection. for piping, it sets up pipes between processes. for redirection, it manipulates file descriptors to read from or write to files. background processes are handled by forking without waiting for the child process to finish.

[read more]