📄 ramdisk.c
字号:
/*****************************************************************************//* RAMDISK.C - Example user-defined device. *//*****************************************************************************/#include <stdlib.h>#include <string.h>#include <file.h>/*****************************************************************************//* This file presents a sample implementation of a user-defined device. *//* The user must define the seven basic functions (open, close, read, *//* write, lseek, unlink, rename). These are expected to behave just like *//* the Unix functions of these names, but this is not strictly necessary to *//* work properly. Also consider something like a TTY device might not be *//* lseek-able, but can still be opened and read from. A device is added *//* using the add_device() RTS function call (q.v.). *//*****************************************************************************//* The low-level interface is based on file names and file descriptors. *//* The file names don't need to be valid Unix file names, but must mean *//* something to the device. File descriptors are integers which represent *//* distinct streams open to a file; there may be more than one descriptor *//* open to each file. The device must keep track of its own file *//* descriptors, which will be used by the calling functions to read and *//* write to the device. If there can only be one instance of a "file" on a *//* device, the file descriptor doesn't matter much, so just pass a *//* non-negative integer such as zero. *//*****************************************************************************//* The RAMDISK device attempts to follow the Unix devices as closely as *//* possible, and even supports file descriptors which point to unlinked *//* files; however, since the RTS doesn't make extensive use of errno, quite *//* a bit of functionality can't be reproduced. *//*****************************************************************************//*****************************************************************************//* RAM_FILES represents the actual ramdisk. It contains files which have *//* been created. These files might not be open. Take note of the unlinked *//* flag; if a file is marked unlinked, it is no longer accessible by name. *//* Attempts to open the file actually create a new entry in RAM_FILES. *//*****************************************************************************//* We could have dynamically reallocated these data structures, but that *//* would just complicate the example. *//*****************************************************************************/#define _NRAMFILES 10#define _NRAMFDS 10static struct ram_file_info { char *name; unsigned char *data; unsigned int size; unsigned int unlinked:1;} ram_files[_NRAMFILES] = { { 0 } };/*****************************************************************************//* RAM_FDS contains information about open file descriptors. *//*****************************************************************************/static struct ram_fd_info { struct ram_file_info *file; unsigned int flags; unsigned int pos;} ram_fds[_NRAMFDS] = { { 0 } };/*****************************************************************************//* *//* RAM_SET_FILE_SIZE() - Truncate or extend current file size. *//* *//*****************************************************************************/static int ram_set_file_size(struct ram_file_info *file, unsigned int newsize){ unsigned int oldsize = file->size; unsigned char *new_data = realloc(file->data, newsize); /*-----------------------------------------------------------------------*/ /* If realloc fails, there's not much we can do about it... */ /*-----------------------------------------------------------------------*/ if (newsize && !new_data) return -1; file->data = (newsize == 0 ? NULL : new_data); file->size = newsize; /*-----------------------------------------------------------------------*/ /* If we have increased the size of the file (possibly by lseeking past */ /* the end), fill the gap with zeros. */ /*-----------------------------------------------------------------------*/ if (newsize > oldsize) memset(file->data + oldsize, '\0', newsize - oldsize); return 1;}/*****************************************************************************//* *//* RAM_FIND_FILE() - Find (possibly creating) a file of a given name *//* *//*****************************************************************************/static struct ram_file_info *ram_find_file(const char *path, int flags){ struct ram_file_info *avail = NULL; int i; /*-----------------------------------------------------------------------*/ /* Go through all the file slots, looking for a non-unlinked file of */ /* the given name. Also look for an empty slot for creating the file */ /* if it doesn't already exist. */ /*-----------------------------------------------------------------------*/ for (i=0; i < _NRAMFILES; i++) if (ram_files[i].name == NULL) avail = &ram_files[i]; else if (!ram_files[i].unlinked && !strcmp(path, ram_files[i].name)) return &ram_files[i]; /*-----------------------------------------------------------------------*/ /* If not found, and the O_CREAT flag was set, go ahead and create an */ /* empty file. */ /*-----------------------------------------------------------------------*/ if (flags & O_CREAT) { avail->name = malloc(strlen(path) + 1); if (!avail->name) return NULL; strcpy(avail->name, path); avail->data = NULL; avail->size = 0; avail->unlinked = 0; return avail; } else return NULL;}/*****************************************************************************//* *//* RAM_MAYBE_UNLINK_FILE() - Delete a file with no open file descriptors. *//* *//*****************************************************************************/static void ram_maybe_unlink_file(struct ram_file_info *file){ int i; /*-----------------------------------------------------------------------*/ /* This function gets called at each attempt to unlink a file, and when */ /* an unlinked file is closed. The file is deleted from disk, but only */ /* if there are no open file descriptors to it. It is perfectly legal */ /* to unlink an open file; the actual file stays on disk until its last */ /* file descriptor is closed. */ /*-----------------------------------------------------------------------*/ for (i=0; i < _NRAMFDS; i++) if (ram_fds[i].file == file) return; if (file->size) free(file->data); free(file->name); file->name = NULL;}/*****************************************************************************//*****************************************************************************/int RAM_open_called = 0; // strictly for testing.../*****************************************************************************//* *//* RAM_OPEN() - Behaves just like open() *//* *//*****************************************************************************/int RAM_open(const char *path, unsigned flags, int llv_fd){ int i, ram_fd = -1; /*-----------------------------------------------------------------------*/ /* Find an available file descriptor */ /*-----------------------------------------------------------------------*/ for (i=0; i < _NRAMFILES; i++) if (ram_fds[i].file == NULL) ram_fd = i; RAM_open_called++; if (ram_fd >= 0) { /*-------------------------------------------------------------------*/ /* Attach a file to the file descriptor, and set the position to */ /* the beginning of the file */ /*-------------------------------------------------------------------*/ ram_fds[ram_fd].file = ram_find_file(path, flags); ram_fds[ram_fd].pos = 0; ram_fds[ram_fd].flags = flags; /*-------------------------------------------------------------------*/ /* If we failed to open the file (it did not exist or we have too */ /* many files), return failure. The file descriptor is still */ /* available because file==NULL. */ /*-------------------------------------------------------------------*/ if (ram_fds[ram_fd].file == NULL) return -1; /*-------------------------------------------------------------------*/ /* Honor O_TRUNC (truncate upon open) */ /*-------------------------------------------------------------------*/ if (flags & O_TRUNC) ram_set_file_size(ram_fds[ram_fd].file, 0); } return ram_fd;}/*****************************************************************************//* *//* RAM_CLOSE() - Behaves just like close() *//* *//*****************************************************************************/int RAM_close(int dev_fd){ struct ram_file_info *file; /*-----------------------------------------------------------------------*/ /* If the given file descriptor is invalid in some way, return failure. */ /*-----------------------------------------------------------------------*/ if (dev_fd < 0 || dev_fd > _NRAMFDS || ram_fds[dev_fd].file == NULL) return -1; /*-----------------------------------------------------------------------*/ /* Make the file descriptor available, and possibly delete the file. */ /*-----------------------------------------------------------------------*/ file = ram_fds[dev_fd].file; ram_fds[dev_fd].file = NULL; if (file->unlinked == 1) ram_maybe_unlink_file(file);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -