dir.c
来自「elinux jffs初始版本 具体了解JFFS的文件系统!」· C语言 代码 · 共 1,279 行 · 第 1/2 页
C
1,279 行
i->next->prev = i->prev; i->prev->next = i->next; DDPRINTK("ncp_free_inode_info: freeing %s\n", i->finfo.i.entryName); ncp_kfree_s(i, sizeof(struct ncp_inode_info)); if (dir == i) return; (dir->nused)--; i = dir; }} voidncp_init_root(struct ncp_server *server){ struct ncp_inode_info *root = &(server->root); struct nw_info_struct *i = &(root->finfo.i); unsigned short dummy; DPRINTK("ncp_init_root: server %s\n", server->m.server_name); DPRINTK("ncp_init_root: i = %x\n", (int)i); root->finfo.opened = 0; i->attributes = aDIR; i->dataStreamSize = 1024; i->dirEntNum = i->DosDirNum = 0; i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */ ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate)); i->nameLen = 0; i->entryName[0] = '\0'; root->state = NCP_INODE_LOOKED_UP; root->nused = 1; root->dir = root; root->next = root->prev = root; return;}intncp_conn_logged_in(struct ncp_server *server){ if (server->m.mounted_vol[0] == '\0') { return 0; } str_upper(server->m.mounted_vol); if (ncp_lookup_volume(server, server->m.mounted_vol, &(server->root.finfo.i)) != 0) { return -ENOENT; } str_lower(server->root.finfo.i.entryName); return 0;}voidncp_free_all_inodes(struct ncp_server *server){ /* Here nothing should be to do. I do not know whether it's better to leave some memory allocated or be stuck in an endless loop */#if 1 struct ncp_inode_info *root = &(server->root); if (root->next != root) { printk("ncp_free_all_inodes: INODES LEFT!!!\n"); } while (root->next != root) { printk("ncp_free_all_inodes: freeing inode\n"); ncp_free_inode_info(root->next); /* In case we have an endless loop.. */ schedule(); }#endif return;}/* We will search the inode that belongs to this name, currently by a complete linear search through the inodes belonging to this filesystem. This has to be fixed. */static struct ncp_inode_info *ncp_find_dir_inode(struct inode *dir, const char *name){ struct ncp_server *server = NCP_SERVER(dir); struct nw_info_struct *dir_info = NCP_ISTRUCT(dir); struct ncp_inode_info *result = &(server->root); if (name == NULL) { return NULL; } do { if ( (result->dir->finfo.i.dirEntNum == dir_info->dirEntNum) && (result->dir->finfo.i.volNumber == dir_info->volNumber) && (strcmp(result->finfo.i.entryName, name) == 0) /* The root dir is never looked up using this * routine. Without the following test a root * directory 'sys' in a volume named 'sys' could * never be looked up, because * server->root->dir==server->root. */ && (result != &(server->root))) { return result; } result = result->next; } while (result != &(server->root)); return NULL;}static int ncp_lookup(struct inode *dir, const char *__name, int len, struct inode **result){ struct nw_file_info finfo; struct ncp_server *server; struct ncp_inode_info *result_info; int found_in_cache; int down_case = 0; char name[len+1]; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_lookup: inode is NULL or not a directory.\n"); iput(dir); return -ENOENT; } server = NCP_SERVER(dir); if (!ncp_conn_valid(server)) { iput(dir); return -EIO; } DPRINTK("ncp_lookup: %s, len %d\n", __name, len); /* Fast cheat for . */ if (len == 0 || (len == 1 && __name[0] == '.')) { *result = dir; return 0; } /* ..and for .. */ if (len == 2 && __name[0] == '.' && __name[1] == '.') { struct ncp_inode_info *parent = NCP_INOP(dir)->dir; if (parent->state == NCP_INODE_CACHED) { parent->state = NCP_INODE_LOOKED_UP; } *result = iget(dir->i_sb, ncp_info_ino(server, parent)); iput(dir); if (*result == 0) { return -EACCES; } else { return 0; } } memcpy(name, __name, len); name[len] = 0; lock_super(dir->i_sb); result_info = ncp_find_dir_inode(dir, name); if (result_info != 0) { if (result_info->state == NCP_INODE_CACHED) { result_info->state = NCP_INODE_LOOKED_UP; } /* Here we convert the inode_info address into an inode number */ *result = iget(dir->i_sb, ncp_info_ino(server, result_info)); unlock_super(dir->i_sb); iput(dir); if (*result == NULL) { return -EACCES; } return 0; } /* If the file is in the dir cache, we do not have to ask the server. */ found_in_cache = 0; ncp_lock_dircache(); if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino)) { int first = c_last_returned_index; int i; i = first; do { DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", i, c_entry[i].i.entryName); if (strcmp(c_entry[i].i.entryName, name) == 0) { DPRINTK("ncp_lookup: found in cache!\n"); finfo.i = c_entry[i].i; found_in_cache = 1; break; } i = (i + 1) % c_size; } while (i != first); } ncp_unlock_dircache(); if (found_in_cache == 0) { int res; DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", NCP_ISTRUCT(dir)->entryName, name); if (ncp_is_server_root(dir)) { str_upper(name); down_case = 1; res = ncp_lookup_volume(server, name, &(finfo.i)); } else { if (!ncp_preserve_case(dir)) { str_upper(name); down_case = 1; } res = ncp_obtain_info(server, NCP_ISTRUCT(dir)->volNumber, NCP_ISTRUCT(dir)->dirEntNum, name, &(finfo.i)); } if (res != 0) { unlock_super(dir->i_sb); iput(dir); return -ENOENT; } } finfo.opened = 0; if (down_case != 0) { str_lower(finfo.i.entryName); } if (!(*result = ncp_iget(dir, &finfo))) { unlock_super(dir->i_sb); iput(dir); return -EACCES; } unlock_super(dir->i_sb); iput(dir); return 0;}static int ncp_create(struct inode *dir, const char *name, int len, int mode, struct inode **result){ struct nw_file_info finfo; __u8 _name[len+1]; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_create: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (!ncp_conn_valid(NCP_SERVER(dir))) { iput(dir); return -EIO; } strncpy(_name, name, len); _name[len] = '\0'; if (!ncp_preserve_case(dir)) { str_upper(_name); } lock_super(dir->i_sb); if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), NCP_ISTRUCT(dir), _name, OC_MODE_CREATE|OC_MODE_OPEN| OC_MODE_REPLACE, 0, AR_READ|AR_WRITE, &finfo) != 0) { unlock_super(dir->i_sb); iput(dir); return -EACCES; } ncp_invalid_dir_cache(dir); if (!ncp_preserve_case(dir)) { str_lower(finfo.i.entryName); } finfo.access = O_RDWR; if (!(*result = ncp_iget(dir, &finfo)) < 0) { ncp_close_file(NCP_SERVER(dir), finfo.file_handle); unlock_super(dir->i_sb); iput(dir); return -EINVAL; } unlock_super(dir->i_sb); iput(dir); return 0; }static intncp_mkdir(struct inode *dir, const char *name, int len, int mode){ int error; struct nw_file_info new_dir; __u8 _name[len+1]; if ( (name[0] == '.') && ( (len == 1) || ( (len == 2) && (name[1] == '.')))) { iput(dir); return -EEXIST; } strncpy(_name, name, len); _name[len] = '\0'; if (!ncp_preserve_case(dir)) { str_upper(_name); } if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_mkdir: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (!ncp_conn_valid(NCP_SERVER(dir))) { iput(dir); return -EIO; } if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), NCP_ISTRUCT(dir), _name, OC_MODE_CREATE, aDIR, 0xffff, &new_dir) != 0) { error = -EACCES; } else { error = 0; ncp_invalid_dir_cache(dir); } iput(dir); return error;}static intncp_rmdir(struct inode *dir, const char *name, int len){ int error; __u8 _name[len+1]; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_rmdir: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (!ncp_conn_valid(NCP_SERVER(dir))) { iput(dir); return -EIO; } if (ncp_find_dir_inode(dir, name) != NULL) { error = -EBUSY; } else { strncpy(_name, name, len); _name[len] = '\0'; if (!ncp_preserve_case(dir)) { str_upper(_name); } if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), NCP_ISTRUCT(dir), _name)) == 0) { ncp_invalid_dir_cache(dir); } else { error = -EACCES; } } iput(dir); return error;}static intncp_unlink(struct inode *dir, const char *name, int len){ int error; __u8 _name[len+1]; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_unlink: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (!ncp_conn_valid(NCP_SERVER(dir))) { iput(dir); return -EIO; } if (ncp_find_dir_inode(dir, name) != NULL) { error = -EBUSY; } else { strncpy(_name, name, len); _name[len] = '\0'; if (!ncp_preserve_case(dir)) { str_upper(_name); } if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), NCP_ISTRUCT(dir), _name)) == 0) { ncp_invalid_dir_cache(dir); } else { error = -EACCES; } } iput(dir); return error;}static intncp_rename(struct inode *old_dir, const char *old_name, int old_len, struct inode *new_dir, const char *new_name, int new_len, int must_be_dir){ int res; char _old_name[old_len+1]; char _new_name[new_len+1]; if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("ncp_rename: old inode is NULL or not a directory\n"); res = -ENOENT; goto finished; } if (!ncp_conn_valid(NCP_SERVER(old_dir))) { res = -EIO; goto finished; } if (!new_dir || !S_ISDIR(new_dir->i_mode)) { printk("ncp_rename: new inode is NULL or not a directory\n"); res = -ENOENT; goto finished; } if ( (ncp_find_dir_inode(old_dir, old_name) != NULL) || (ncp_find_dir_inode(new_dir, new_name) != NULL)) { res = -EBUSY; goto finished; } strncpy(_old_name, old_name, old_len); _old_name[old_len] = '\0'; if (!ncp_preserve_case(old_dir)) { str_upper(_old_name); } strncpy(_new_name, new_name, new_len); _new_name[new_len] = '\0'; if (!ncp_preserve_case(new_dir)) { str_upper(_new_name); } res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), NCP_ISTRUCT(old_dir), _old_name, NCP_ISTRUCT(new_dir), _new_name); if (res == 0) { ncp_invalid_dir_cache(old_dir); ncp_invalid_dir_cache(new_dir); } else { res = -EACCES; } finished: iput(old_dir); iput(new_dir); return res;}/* The following routines are taken directly from msdos-fs *//* Linear day numbers of the respective 1sts in non-leap years. */static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */extern struct timezone sys_tz;static intutc2local(int time){ return time - sys_tz.tz_minuteswest*60 + sys_tz.tz_dsttime*3600;}static intlocal2utc(int time){ return time + sys_tz.tz_minuteswest*60 - sys_tz.tz_dsttime*3600;}/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */intncp_date_dos2unix(unsigned short time,unsigned short date){ int month,year,secs; month = ((date >> 5) & 15)-1; year = date >> 9; secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && month < 2 ? 1 : 0)+3653); /* days since 1.1.70 plus 80's leap day */ return local2utc(secs);}/* Convert linear UNIX date to a MS-DOS time/date pair. */voidncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date){ int day,year,nl_day,month; unix_date = utc2local(unix_date); *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ (((unix_date/3600) % 24) << 11); day = unix_date/86400-3652; year = day/365; if ((year+3)/4+365*year > day) year--; day -= (year+3)/4+365*year; if (day == 59 && !(year & 3)) { nl_day = day; month = 2; } else { nl_day = (year & 3) || day <= 59 ? day : day-1; for (month = 0; month < 12; month++) if (day_n[month] > nl_day) break; } *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?