/* * KML REINT * * Copryright (C) 1996 Arthur Ma * * Copyright (C) 2000 Mountainview Data, Inc. */ #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kmlreint_pre_secure (struct kml_rec *rec); static void kmlreint_post_secure (struct kml_rec *rec); static void kmlreint_pre_secure (struct kml_rec *rec) { if (current->fsuid != current->uid) CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsuid\n"); if (current->fsgid != current->gid) CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsgid\n"); current->fsuid = rec->rec_head.uid; current->fsgid = rec->rec_head.fsgid; } static void kmlreint_post_secure (struct kml_rec *rec) { current->fsuid = current->uid; current->fsgid = current->gid; /* current->egid = current->gid; */ /* ????????????? */ } static int reint_create (int slot_offset, struct kml_rec *rec) { struct lento_vfs_context info; struct kml_create *create = &rec->rec_kml.create; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; CDEBUG (D_KML, "=====REINT_CREATE::%s\n", create->path); old_fs = get_fs(); set_fs (get_ds()); error = lento_create(create->path, create->mode, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_open (int slot_offset, struct kml_rec *rec) { return 0; } static int reint_mkdir (int slot_offset, struct kml_rec *rec) { struct lento_vfs_context info; struct kml_mkdir *mkdir = &rec->rec_kml.mkdir; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_mkdir (mkdir->path, mkdir->mode, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_rmdir (int slot_offset, struct kml_rec *rec) { struct kml_rmdir *rmdir = &rec->rec_kml.rmdir; struct lento_vfs_context info; mm_segment_t old_fs; char *name; int error; ENTRY; kmlreint_pre_secure (rec); name = bdup_printf ("%s/%s", rmdir->path, rmdir->name); if (name == NULL) { kmlreint_post_secure (rec); EXIT; return -ENOMEM; } info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_rmdir (name, &info); set_fs (old_fs); PRESTO_FREE (name, strlen (name) + 1); kmlreint_post_secure (rec); EXIT; return error; } static int reint_link (int slot_offset, struct kml_rec *rec) { struct kml_link *link = &rec->rec_kml.link; struct lento_vfs_context info; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_link (link->sourcepath, link->targetpath, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_unlink (int slot_offset, struct kml_rec *rec) { struct kml_unlink *unlink = &rec->rec_kml.unlink; struct lento_vfs_context info; mm_segment_t old_fs; int error; char *name; ENTRY; kmlreint_pre_secure (rec); name = bdup_printf ("%s/%s", unlink->path, unlink->name); if (name == NULL) { kmlreint_post_secure (rec); EXIT; return -ENOMEM; } info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_unlink (name, &info); set_fs (old_fs); PRESTO_FREE (name, strlen (name)); kmlreint_post_secure (rec); EXIT; return error; } static int reint_symlink (int slot_offset, struct kml_rec *rec) { struct kml_symlink *symlink = &rec->rec_kml.symlink; struct lento_vfs_context info; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_symlink (symlink->targetpath, symlink->sourcepath, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_rename (int slot_offset, struct kml_rec *rec) { struct kml_rename *rename = &rec->rec_kml.rename; struct lento_vfs_context info; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_rename (rename->sourcepath, rename->targetpath, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_setattr (int slot_offset, struct kml_rec *rec) { struct kml_setattr *setattr = &rec->rec_kml.setattr; struct lento_vfs_context info; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = setattr->iattr.ia_attr_flags; old_fs = get_fs(); set_fs (get_ds()); error = lento_setattr (setattr->path, &setattr->iattr, &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } static int reint_mknod (int slot_offset, struct kml_rec *rec) { struct kml_mknod *mknod = &rec->rec_kml.mknod; struct lento_vfs_context info; mm_segment_t old_fs; int error; ENTRY; kmlreint_pre_secure (rec); info.slot_offset = slot_offset; info.recno = rec->rec_tail.recno; info.kml_offset = rec->rec_kml_offset; info.flags = 0; old_fs = get_fs(); set_fs (get_ds()); error = lento_mknod (mknod->path, mknod->mode, MKDEV(mknod->major, mknod->minor), &info); set_fs (old_fs); kmlreint_post_secure (rec); EXIT; return error; } int kml_reint (char *mtpt, int slot_offset, struct kml_rec *rec) { int error = 0; switch (rec->rec_head.opcode) { case KML_CREATE: error = reint_create (slot_offset, rec); break; case KML_OPEN: error = reint_open (slot_offset, rec); break; case KML_CLOSE: /* error = reint_close (slot_offset, rec); force the system to return to lento */ error = KML_CLOSE_BACKFETCH; break; case KML_MKDIR: error = reint_mkdir (slot_offset, rec); break; case KML_RMDIR: error = reint_rmdir (slot_offset, rec); break; case KML_UNLINK: error = reint_unlink (slot_offset, rec); break; case KML_LINK: error = reint_link (slot_offset, rec); break; case KML_SYMLINK: error = reint_symlink (slot_offset, rec); break; case KML_RENAME: error = reint_rename (slot_offset, rec); break; case KML_SETATTR: error = reint_setattr (slot_offset, rec); break; case KML_MKNOD: error = reint_mknod (slot_offset, rec); break; default: CDEBUG (D_KML, "wrong opcode::%d\n", rec->rec_head.opcode); return -EBADF; } if (error != 0 && error != KML_CLOSE_BACKFETCH) CDEBUG (D_KML, "KML_ERROR::error = %d\n", error); return error; } /* return the old mtpt */ /* struct fs_struct { atomic_t count; int umask; struct dentry * root, * pwd; }; */ static int do_set_fs_root (struct dentry *newroot, struct dentry **old_root) { struct dentry *de = current->fs->root; current->fs->root = newroot; if (old_root != (struct dentry **) NULL) *old_root = de; return 0; } static int set_system_mtpt (char *mtpt, struct dentry **old_root) { struct nameidata nd; struct dentry *dentry; int error; if (path_init(pathname, LOOKUP_PARENT, &nd)) error = path_walk(mtpt, &nd); if (error) { CDEBUG (D_KML, "Yean!!!!::Can't find mtpt::%s\n", mtpt); return error; } dentry = nd.dentry; error = do_set_fs_root (dentry, old_root); path_release (&nd); return error; } int kml_reintbuf (struct kml_fsdata *kml_fsdata, char *mtpt, struct kml_rec **close_rec) { struct kml_rec *rec = NULL; struct list_head *head, *tmp; struct dentry *old_root; int error = 0; head = &kml_fsdata->kml_reint_cache; if (list_empty(head)) return 0; if (kml_fsdata->kml_reint_current == NULL || kml_fsdata->kml_reint_current == head->next) return 0; error = set_system_mtpt (mtpt, &old_root); if (error) return error; tmp = head->next; while (error == 0 && tmp != head ) { rec = list_entry(tmp, struct kml_rec, kml_optimize.kml_chains); error = kml_reint (mtpt, rec->rec_kml_offset, rec); tmp = tmp->next; } do_set_fs_root (old_root, NULL); if (error == KML_CLOSE_BACKFETCH) *close_rec = rec; kml_fsdata->kml_reint_current = tmp; return error; }