📄 dir.c
字号:
/* * FILE NAME fs/pramfs/dir.c * * BRIEF DESCRIPTION * * File operations for directories. * * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com> * * Copyright 2003 Sony Corporation * Copyright 2003 Matsushita Electric Industrial Co., Ltd. * 2003-2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/fs.h>#include <linux/pram_fs.h>#include <linux/pagemap.h>/* * Parent is locked. */int pram_add_link (struct dentry * dentry, struct inode * inode){ struct inode * dir = dentry->d_parent->d_inode; struct pram_inode * pidir, * pi, * pitail = NULL; pram_off_t tail_ino, prev_ino; const char *name = dentry->d_name.name; int namelen = dentry->d_name.len > PRAM_NAME_LEN ? PRAM_NAME_LEN : dentry->d_name.len; struct super_block * sb = dir->i_sb; pidir = pram_get_inode(sb, dir->i_ino); pi = pram_get_inode(sb, inode->i_ino); dir->i_mtime = dir->i_ctime = CURRENT_TIME; tail_ino = pidir->i_type.dir.tail; if (tail_ino != 0) { pitail = pram_get_inode(sb, tail_ino); pram_lock_inode(sb, pitail); pitail->i_d.d_next = inode->i_ino; pram_unlock_inode(sb, pitail); prev_ino = tail_ino; pram_lock_inode(sb, pidir); pidir->i_type.dir.tail = inode->i_ino; pidir->i_mtime = dir->i_mtime.tv_sec; pidir->i_ctime = dir->i_ctime.tv_sec; pram_unlock_inode(sb, pidir); } else { // the directory is empty prev_ino = 0; pram_lock_inode(sb, pidir); pidir->i_type.dir.head = pidir->i_type.dir.tail = inode->i_ino; pidir->i_mtime = dir->i_mtime.tv_sec; pidir->i_ctime = dir->i_ctime.tv_sec; pram_unlock_inode(sb, pidir); } pram_lock_inode(sb, pi); pi->i_d.d_prev = prev_ino; pi->i_d.d_parent = dir->i_ino; memcpy(pi->i_d.d_name, name, namelen); pi->i_d.d_name[namelen] = '\0'; pram_unlock_inode(sb, pi); return 0;}int pram_remove_link(struct inode * inode){ struct super_block * sb = inode->i_sb; struct pram_inode * prev = NULL; struct pram_inode * next = NULL; struct pram_inode * pidir, * pi; pi = pram_get_inode(sb, inode->i_ino); pidir = pram_get_inode(sb, pi->i_d.d_parent); if (!pidir) return -EACCES; if (inode->i_ino == pidir->i_type.dir.head) { // first inode in directory next = pram_get_inode(sb, pi->i_d.d_next); if (next) { pram_lock_inode(sb, next); next->i_d.d_prev = 0; pram_unlock_inode(sb, next); pram_lock_inode(sb, pidir); pidir->i_type.dir.head = pi->i_d.d_next; } else { pram_lock_inode(sb, pidir); pidir->i_type.dir.head = pidir->i_type.dir.tail = 0; } pram_unlock_inode(sb, pidir); } else if (inode->i_ino == pidir->i_type.dir.tail) { // last inode in directory prev = pram_get_inode(sb, pi->i_d.d_prev); pram_lock_inode(sb, prev); prev->i_d.d_next = 0; pram_unlock_inode(sb, prev); pram_lock_inode(sb, pidir); pidir->i_type.dir.tail = pi->i_d.d_prev; pram_unlock_inode(sb, pidir); } else { // somewhere in the middle prev = pram_get_inode(sb, pi->i_d.d_prev); next = pram_get_inode(sb, pi->i_d.d_next); if (prev && next) { pram_lock_inode(sb, prev); prev->i_d.d_next = pi->i_d.d_next; pram_unlock_inode(sb, prev); pram_lock_inode(sb, next); next->i_d.d_prev = pi->i_d.d_prev; pram_unlock_inode(sb, next); } } pram_lock_inode(sb, pi); pi->i_d.d_next = pi->i_d.d_prev = pi->i_d.d_parent = 0; pram_unlock_inode(sb, pi); return 0;}#define S_SHIFT 12static unsigned int dtype_by_mode[S_IFMT >> S_SHIFT] = { [S_IFREG >> S_SHIFT] = DT_REG, [S_IFDIR >> S_SHIFT] = DT_DIR, [S_IFCHR >> S_SHIFT] = DT_CHR, [S_IFBLK >> S_SHIFT] = DT_BLK, [S_IFIFO >> S_SHIFT] = DT_FIFO, [S_IFSOCK >> S_SHIFT] = DT_SOCK, [S_IFLNK >> S_SHIFT] = DT_LNK,};static intpram_readdir (struct file * filp, void * dirent, filldir_t filldir){ struct inode *inode = filp->f_dentry->d_inode; struct super_block * sb = inode->i_sb; struct pram_inode * pi; int namelen, ret=0; char *name; ino_t ino; if (filp->f_pos >> 32) return 0; pi = pram_get_inode(sb, inode->i_ino); switch ((unsigned long)filp->f_pos) { case 0: ret = filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR); filp->f_pos++; return ret; case 1: ret = filldir(dirent, "..", 2, 1, pi->i_d.d_parent, DT_DIR); ino = pi->i_type.dir.head; filp->f_pos = ino ? ino : 2; return ret; case 2: ino = pi->i_type.dir.head; if (ino) { filp->f_pos = ino; pi = pram_get_inode(sb, ino); break; } else { /* the directory is empty */ filp->f_pos = 2; return 0; } case 3: return 0; default: ino = filp->f_pos; pi = pram_get_inode(sb, ino); break; } while (pi && !pi->i_links_count) { ino = filp->f_pos = pi->i_d.d_next; pi = pram_get_inode(sb, ino); } if (pi) { name = pi->i_d.d_name; namelen = strlen(name); ret = filldir(dirent, name, namelen, filp->f_pos, ino, dtype_by_mode[(pi->i_mode & S_IFMT)>>S_SHIFT]); filp->f_pos = pi->i_d.d_next ? pi->i_d.d_next : 3; } else filp->f_pos = 3; return ret;}const struct file_operations pram_dir_operations = { .read = generic_read_dir, .readdir = pram_readdir, .ioctl = pram_ioctl, .fsync = pram_sync_file,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -