📄 fs_incore.c
字号:
if (((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || (long )gid != l) return -EINVAL; if (*cp != '\0') return -EINVAL; } err = 0; dev = _sysio_dev_alloc(); mnt = NULL; rootpb = NULL; rooti = NULL; fs = NULL; icino = NULL; icfs = NULL; /* * Create new FS. */ icfs = malloc(sizeof(struct incore_filesys)); if (!icfs) { err = -ENOMEM; goto error; } (void )memset(icfs, 0, sizeof(struct incore_filesys)); LIST_INIT(&icfs->icfs_icinodes); /* * Create root i-node. */ (void )memset(&stat, 0, sizeof(stat)); stat.st_dev = dev; inum = incore_inum_alloc();#ifdef HAVE__ST_INO stat.__st_ino = inum; #endif stat.st_mode = S_IFDIR | (mode & 07777); stat.st_nlink = 2; stat.st_uid = uid; stat.st_gid = gid; stat.st_size = 0; stat.st_blksize = INCORE_BLKSIZE; stat.st_blocks = 0; stat.st_ctime = stat.st_mtime = stat.st_atime = 0; stat.st_ino = inum; icino = incore_directory_new(icfs, NULL, &stat); if (!icino) return -ENOSPC; icino->ici_st.st_atime = icino->ici_st.st_mtime; fs = _sysio_fs_new(&incore_fs_ops, (flags & MOUNT_F_RO) ? FS_F_RO : 0, icfs); if (!fs) { err = -ENOMEM; goto error; } /* * Create root for system. * * Persistent across remounts because we ask for immunity. */ rooti = _sysio_i_new(fs, &icino->ici_fileid, &icino->ici_st, 1, &_sysio_incore_dir_ops, icino); if (!rooti) { err = -ENOMEM; goto error; } rootpb = _sysio_pb_new(&noname, NULL, rooti); if (!rootpb) { err = -ENOMEM; goto error; } /* * Have path-node specified by the given source argument. Let the * system finish the job, now. */ mnt = NULL; err = _sysio_do_mount(fs, rootpb, flags, tocover, &mnt); if (err) goto error; *mntp = mnt; goto out;error: if (mnt && _sysio_do_unmount(mnt) != 0) abort(); if (rootpb) { _sysio_pb_gone(rootpb); rooti = NULL; } if (rooti) I_RELE(rooti); if (fs) { FS_RELE(fs); goto out; } if (icino) { incore_i_destroy(icino); goto out; } if (icfs) { free(icfs); goto out; }out: return err;}static void_sysio_incore_fsop_gone(struct filesys *fs){ struct incore_filesys *icfs; struct incore_inode *icino, *oicino; icfs = FS2ICFS(fs); /* * Free up i-node resource associated with this file system. */ icino = icfs->icfs_icinodes.lh_first; while (icino) { oicino = icino; icino = icino->ici_link.le_next; incore_i_destroy(oicino); } /* * Free the FS record. */ free(icfs);}/* * A directory search engine. Various functions are carried out by * supplying appropriate callback functions. * * The two arguments, entry and hole, are called, if not null, for each * directory entry and hole, respectively. */static void *incore_directory_probe(void *data, size_t siz, _SYSIO_OFF_T origin#ifndef _DIRENT_HAVE_D_OFF __IS_UNUSED#endif , probe_ty entry, probe_ty hole, void *arg){ struct intnl_dirent *de; void *p; size_t n; de = data; for (;;) {#ifdef _DIRENT_HAVE_D_OFF assert(de->d_off);#else assert(de->d_reclen);#endif if (entry && (p = (*entry)(de, de->d_reclen, arg))) return p; n =#ifdef _DIRENT_HAVE_D_OFF de->d_off - origin;#else ((void *)de - data) + de->d_reclen;#endif if (hole) { p = (*hole)((void *)de, de->d_reclen, arg); if (p) return p; } if (n >= siz) break; de = (struct intnl_dirent *)((char *)data + n); } return NULL;}static struct intnl_dirent *incore_directory_match(struct intnl_dirent *de, size_t reclen, struct lookup_data *ld){ size_t len;#if defined(BSD) || defined(REDSTORM) if (IFTODT(de->d_type) == DT_WHT) return NULL;#endif#ifdef _DIRENT_HAVE_D_NAMLEN len = de->d_namlen;#else { const char *cp, *end; cp = de->d_name; end = (const char *)de + reclen; while (cp < end && *cp != '\0') cp++; len = cp - de->d_name; }#endif if (ld->name->len == len && strncmp(de->d_name, ld->name->name, ld->name->len) == 0) return de; ld->de = de; return NULL;}static int_sysio_incore_dirop_lookup(struct pnode *pno, struct inode **inop, struct intent *intnt __IS_UNUSED, const char *path __IS_UNUSED){ struct inode *ino; struct intnl_dirent *de; struct incore_inode *icino; struct lookup_data lookup_data; struct file_identifier fileid;#ifdef notdef struct inode_ops *ops;#endif /* * Revalidate? */ if (*inop) { icino = I2IC(*inop); assert(icino); (*inop)->i_stbuf = icino->ici_st; return 0; } ino = pno->p_parent->p_base->pb_ino; icino = I2IC(ino); INCORE_LD_INIT(&lookup_data, ULONG_MAX, &pno->p_base->pb_name); de = incore_directory_probe(icino->ici_data, icino->ici_st.st_size, 0, (probe_ty )incore_directory_match, NULL, &lookup_data); if (!de) return -ENOENT; fileid.fid_data = &de->d_ino; fileid.fid_len = sizeof(de->d_ino); ino = _sysio_i_find(ino->i_fs, &fileid);#ifdef notdef if (ino) goto out; icino->ici_fileid.fid_data = &icino->ici_st.st_ino; icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino); ops = NULL; switch (icino->ici_st.st_mode & S_IFMT) { case S_IFDIR: ops = &_sysio_incore_dir_ops; break; case S_IFREG: ops = &_sysio_incore_file_ops; break; default: break; } if (!ops) abort(); ino = _sysio_i_new(ino->i_fs, &icino->ici_fileid, &icino->ici_st 1, ops, icino);#endif if (!ino) return -ENOMEM;#ifdef notdefout:#endif *inop = ino; return 0;}static int_sysio_incore_inop_getattr(struct pnode *pno, struct inode *ino, struct intnl_stat *stbuf){ struct incore_inode *icino; if (!ino) ino = pno->p_base->pb_ino; icino = I2IC(ino); *stbuf = icino->ici_st; return 0;}static int_sysio_incore_inop_setattr(struct pnode *pno, struct inode *ino, unsigned mask, struct intnl_stat *stbuf){ struct incore_inode *icino; int err; if (!ino) ino = pno->p_base->pb_ino; if (!ino) return -EBADF; icino = I2IC(ino); err = 0; if (mask & SETATTR_LEN) { err = incore_trunc(icino, stbuf->st_size, 1); if (err) goto out; mask &= ~SETATTR_LEN; } if (mask & SETATTR_MODE) { icino->ici_st.st_mode = (icino->ici_st.st_mode & S_IFMT) | (stbuf->st_mode & 07777); } if (mask & SETATTR_MTIME) icino->ici_st.st_mtime = stbuf->st_mtime; if (mask & SETATTR_ATIME) icino->ici_st.st_atime = stbuf->st_atime; if (mask & SETATTR_UID) icino->ici_st.st_uid = stbuf->st_uid; if (mask & SETATTR_GID) icino->ici_st.st_gid = stbuf->st_gid; icino->ici_st.st_ctime = time(NULL); ino->i_stbuf = icino->ici_st;out: return err;}static void *incore_directory_position(struct intnl_dirent *de, size_t reclen __IS_UNUSED, void *p){ return (void *)de >= p ? de : NULL;}struct copy_info { void *data; size_t nbytes; unsigned count;};/* * Eumeration callback. * * Note: * Whiteout entries are never returned. */static void *incore_directory_enumerate(struct intnl_dirent *de, size_t reclen, struct copy_info *cinfo) {#ifdef DT_WHT if (de->d_type == DT_WHT) { /* * Keep going but skip the copy. */ return NULL; }#endif cinfo->count++; if (reclen > cinfo->nbytes) return de; (void *)memcpy(cinfo->data, de, reclen); cinfo->data = (char *)cinfo->data + reclen; cinfo->nbytes -= reclen; return NULL;}static ssize_t_sysio_incore_dirop_filldirentries(struct inode *ino, _SYSIO_OFF_T *posp, char *buf, size_t nbytes){ struct incore_inode *icino = I2IC(ino); off_t off; struct intnl_dirent *de; struct copy_info copy_info; if (*posp >= icino->ici_st.st_size) return 0; de = incore_directory_probe(icino->ici_data, icino->ici_st.st_size, *posp, (probe_ty )incore_directory_position, NULL, (char *)icino->ici_data + *posp); if (!de) { /* * Past EOF. */ return 0; } copy_info.data = buf; copy_info.nbytes = nbytes; copy_info.count = 0; off = (char *)de - (char *)icino->ici_data; de = incore_directory_probe(de, icino->ici_st.st_size - off, off, (probe_ty )incore_directory_enumerate, NULL, ©_info); icino->ici_st.st_atime = time(NULL); if (nbytes == copy_info.nbytes && copy_info.count) return -EINVAL; nbytes -= copy_info.nbytes;#if 0 if (!nbytes) return -EOVERFLOW;#endif *posp += nbytes; return (ssize_t )nbytes;}static struct intnl_dirent *incore_directory_best_fit(void *data, size_t len, struct lookup_data *ld){ if (!ld->hole.len || len < ld->hole.len) { ld->hole.p = data; ld->hole.len = len; } return NULL;}static intincore_directory_insert(struct incore_inode *parent, struct qstr *name, ino_t inum, unsigned char type){ size_t reclen; struct lookup_data lookup_data; struct intnl_dirent *de; size_t xt; size_t n; size_t r; reclen = INCORE_D_RECLEN(name->len); INCORE_LD_INIT(&lookup_data, reclen, name); de = incore_directory_probe(parent->ici_data, parent->ici_st.st_size, 0, (probe_ty )incore_directory_match, (probe_ty )incore_directory_best_fit, &lookup_data); if (de) return -EEXIST; de = lookup_data.de; xt = (char *)lookup_data.de - (char *)parent->ici_data; n =#ifdef _DIRENT_HAVE_D_OFF de->d_off;#else xt + de->d_reclen;#endif r =#ifdef _DIRENT_HAVE_D_OFF de->d_reclen;#else INCORE_D_RECLEN(de->d_namlen);#endif if (!parent->ici_st.st_size || xt + r + reclen > (size_t )parent->ici_st.st_size) { int err; err = incore_trunc(parent, xt + r + reclen, 1); if (err) return err; de = (struct intnl_dirent *)((char *)parent->ici_data + xt); n = parent->ici_st.st_size; }#ifdef _DIRENT_HAVE_D_OFF de->d_off = xt + r; /* trim */#else de->d_reclen = r;#endif de = (struct intnl_dirent *)((char *)de + r); /* reposition */ xt += r;#ifndef _DIRENT_HAVE_D_OFF /* * Will we split this hole or use all of it? */ if (lookup_data.hole.len - reclen && lookup_data.hole.len - reclen <= INCORE_D_RECLEN(1)) reclen = lookup_data.hole.len;#endif /* * Insert new. */ de->d_ino = inum;#ifdef _DIRENT_HAVE_D_OFF de->d_off = n;#endif de->d_reclen = reclen; de->d_type = type; (void )memcpy(de->d_name, name->name, name->len);#ifdef _DIRENT_HAVE_D_NAMLEN de->d_namlen = name->len;#endif#ifndef _DIRENT_HAVE_D_OFF xt += reclen; if (n - xt) { /* * White-out remaining part of the hole. */ (void *)de += reclen; de->d_ino = 0; de->d_reclen = n - xt; de->d_type = DT_WHT; de->d_namlen = 0; }#endif /* * Update attributes to reflect the new entry. */ parent->ici_st.st_nlink++; assert(parent->ici_st.st_nlink); parent->ici_st.st_atime = parent->ici_st.st_mtime = time(NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -