⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 Bycore是一个嵌入式操作系统内核。Bycore包括内存管理、任务管理、中断管理、任务互斥、同步与通信管理等功能。Bycore全部由C语言完成
💻 C
字号:
/** *  fs.c - A set of APIs that used to handle files and devices. * *  Copyright (C) 2008  ZhangHu *  All rights reserved. *  E-MAIL: anmnmnly@gmail.com * *  This program is free software: you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation, either version 3 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program.  If not, see <http://www.gnu.org/licenses/>. */#include "include/types.h"#include "include/irq.h"#include "include/list.h"#include "include/mem.h"#include "fs/fs.h"#include "drivers/chdev.h"#include "common/string.h"static uword_t file_fd = 0;/** * add_fd_node_to_current_task: Add a file node to current task. * @list: Pointer to the file node. * @return: * * @notes: */static void add_fd_node_to_current_task(slist_t *list){    if(list == NULL) {        return;    }    mac_disable_irq();    add_node_single_list_head(&(current()->fd_node), list);    mac_enable_irq();}/** * find_file_node_from_current_task: find a file node according to 'fd'. * @fd: file descriptor. * @return: file_node Pointer. * * @notes: */static file_node *get_file_node_from_current_task(word_t fd) {    slist_t *slist;    file_node *fn;    slist = (current())->fd_node.next;    while(slist != NULL) {        fn = mac_find_entry(slist, file_node, link);        if(fn->fd == fd) {            break;        } else {            slist = slist->next;        }    }    if(slist == NULL) {        return NULL;    }    return fn;}/** * delete_file_node_from_current_task: delete a file node from current task. * @fd: file descriptor. * @return: TRUE if successful, otherwise FALSE. * * @notes: */static void delete_file_node_from_current_task(file_node *fn) {    if(fn == NULL) {        return;    }    mac_disable_irq();    del_node_single_list(&(current()->fd_node), &fn->link);    mac_enable_irq();    kfree(fn);}/** * get_fd_number - Get a file descriptor. * @return: return a free file descriptor. * * @notes: */static uword_t get_fd_number(void) {    mac_disable_irq();    if(file_fd++ >= (~0)) {        file_fd = 0;    }    mac_enable_irq();    return file_fd;}/** * open - It opens a device. * @path: Pointer to a string that describes the name of a device. * @return: File descriptor. * * @notes: */word_t open(const char_t *path) {    device_t *dev = NULL;    chdev_t *pchdev = NULL;    file_node *fn = NULL;    dev = device_open(path);    if(dev == NULL) {        return -1;    }    if((fn = (file_node*)kmalloc(sizeof(file_node))) == NULL) {        return -1;    }	kmemset(fn, 0, sizeof(file_node));    fn->fd = get_fd_number();    fn->device = dev;    add_fd_node_to_current_task(&fn->link);    if(dev->dev_type == CHDEV) {        pchdev = (chdev_t*)dev;        if((pchdev->op != NULL) && (pchdev->op->open != NULL)) {            spin_lock(&fn->device->lock);            pchdev->op->open();            spin_unlock(&fn->device->lock);        }    }    return fn->fd;}/** * write - It writes data to a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @buf: Pointer to a data buffer. * @nbytes: The length of data buffer. * @return: The number of wrote data. * * @notes: */uword_t write(word_t fd, const char_t *buf, uword_t nbytes) {    file_node *fn = NULL;    chdev_t *pchdev = NULL;    int result = 0;    fn = get_file_node_from_current_task(fd);    if(fn == NULL) {        return result;    }    if(fn->device->dev_type == CHDEV) {        pchdev = (chdev_t*)fn->device;        if((pchdev->op != NULL) && (pchdev->op->write != NULL)) {            spin_lock(&fn->device->lock);            result = pchdev->op->write(buf, nbytes,                                       ((chdev_t*)fn->device)->loff);            spin_unlock(&fn->device->lock);        }    }    return result;}/** * write - It reads data from a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @buf: Pointer to a data buffer. * @nbytes: The length of data buffer. * @return: The number of read data. * * @notes: */uword_t read(word_t fd, char_t *buf, uword_t nbytes) {    file_node *fn = NULL;    chdev_t *pchdev = NULL;    word_t result = 0;    fn = get_file_node_from_current_task(fd);    if(fn == NULL) {        return result;    }    if(fn->device->dev_type == CHDEV) {        pchdev = (chdev_t*)fn->device;        if((pchdev->op != NULL) && (pchdev->op->read != NULL)) {            spin_lock(&fn->device->lock);            result = pchdev->op->read(buf, nbytes,                                      ((chdev_t*)fn->device)->loff);            spin_unlock(&fn->device->lock);        }    }    return result;}/** * llseek - It modifies write-read offset. * @fd: A file descriptor returned by 'open()'. * @loff: New write-read offset. * @return: The new write-read offset. * * @notes: */loff_t llseek(word_t fd, loff_t loff) {    file_node *fn = NULL;    chdev_t *pchdev = NULL;    fn = get_file_node_from_current_task(fd);    if(fn == NULL) {        return -1;    }    if(fn->device->dev_type == CHDEV) {        pchdev = (chdev_t*)fn->device;        spin_lock(&fn->device->lock);        pchdev->loff = loff;        spin_unlock(&fn->device->lock);    }    return loff;}/** * ioctl - It modifies properties of a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @cmd: Command cord. * @arg: Pointer to parameters of command. * @return: TRUE if successful, otherwise FALSE. * * @notes: ioctcl dosen't explain or execute any command. It only transfer *         command and it's parameters to device driver. */word_t ioctl(word_t fd, uword_t cmd, void *arg) {    file_node *fn = NULL;    chdev_t *pchdev = NULL;    fn = get_file_node_from_current_task(fd);    if(fn == NULL) {        return FALSE;    }    if(fn->device->dev_type == CHDEV) {        pchdev = (chdev_t*)fn->device;        if((pchdev->op != NULL) && (pchdev->op->ioctl != NULL)) {            spin_lock(&fn->device->lock);            pchdev->op->ioctl(cmd, arg);            spin_unlock(&fn->device->lock);            return TRUE;        }    }    return FALSE;}/** * close - It closes a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @return: TRUE if successful, otherwise FALSE. * * @notes: */word_t close(word_t fd) {    file_node *fn = NULL;    chdev_t *pchdev = NULL;    fn = get_file_node_from_current_task(fd);    if(fn == NULL) {        return FALSE;    }    if(fn->device->dev_type == CHDEV) {        pchdev = (chdev_t*)fn->device;        if((pchdev->op != NULL) && (pchdev->op->close != NULL)) {            spin_lock(&fn->device->lock);            pchdev->op->close();            device_close(fn->device);            spin_unlock(&fn->device->lock);        }    }    delete_file_node_from_current_task(fn);    return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -