int main (int argc, char **argv) { error_t err; mach_port_t bootstrap; /* Initialize the diskfs library, parse arguments, and open the store. This starts the first diskfs thread for us. */ store = diskfs_init_main (&startup_argp, argc, argv, &store_parsed, &bootstrap); if (store->size < SBLOCK_OFFS + SBLOCK_SIZE) ext2_panic ("device too small for superblock (%Ld bytes)", store->size); if (store->log2_blocks_per_page < 0) ext2_panic ("device block size (%zu) greater than page size (%zd)", store->block_size, vm_page_size); /* Map the entire disk. */ create_disk_pager (); pokel_init (&global_pokel, diskfs_disk_pager, disk_cache); map_hypermetadata (); /* Set diskfs_root_node to the root inode. */ err = diskfs_cached_lookup (EXT2_ROOT_INO, &diskfs_root_node); if (err) ext2_panic ("can't get root: %s", strerror (err)); else if ((diskfs_root_node->dn_stat.st_mode & S_IFMT) == 0) ext2_panic ("no root node!"); pthread_mutex_unlock (&diskfs_root_node->lock); /* Now that we are all set up to handle requests, and diskfs_root_node is set properly, it is safe to export our fsys control port to the outside world. */ diskfs_startup_diskfs (bootstrap, 0); /* and so we die, leaving others to do the real work. */ pthread_exit (NULL); /* NOTREACHED */ return 0; }
/* The user must define this function. Allocate a new node to be of mode MODE in locked directory DP (don't actually set the mode or modify the dir, that will be done by the caller); the user responsible for the request can be identified with CRED. Set *NP to be the newly allocated node. */ error_t diskfs_alloc_node (struct node *dir, mode_t mode, struct node **node) { error_t err; int sex, block; struct node *np; struct stat *st; ino_t inum; assert (!diskfs_readonly); inum = ext2_alloc_inode (dir->cache_id, mode); if (inum == 0) return ENOSPC; err = diskfs_cached_lookup (inum, &np); if (err) return err; st = &np->dn_stat; if (st->st_blocks) { st->st_blocks = 0; np->dn_set_ctime = 1; } /* Zero out the block pointers in case there's some noise left on disk. */ for (block = 0; block < EXT2_N_BLOCKS; block++) if (np->dn->info.i_data[block] != 0) { np->dn->info.i_data[block] = 0; np->dn_set_ctime = 1; } if (np->dn->info_i_translator != 0) { np->dn->info_i_translator = 0; np->dn_set_ctime = 1; } st->st_mode &= ~S_IPTRANS; if (np->allocsize) { st->st_size = 0; np->allocsize = 0; np->dn_set_ctime = 1; } /* Propagate initial inode flags from the directory, as Linux does. */ np->dn->info.i_flags = ext2_mask_flags(mode, dir->dn->info.i_flags & EXT2_FL_INHERITED); st->st_flags = 0; /* * Set up a new generation number for this inode. */ pthread_spin_lock (&generation_lock); sex = diskfs_mtime->seconds; if (++next_generation < (u_long)sex) next_generation = sex; st->st_gen = next_generation; pthread_spin_unlock (&generation_lock); alloc_sync (np); *node = np; return 0; }
/* Return in FILE & FILE_TYPE the file in FSYS corresponding to the NFS file handle HANDLE & HANDLE_LEN. */ error_t diskfs_S_fsys_getfile (mach_port_t fsys, mach_port_t reply, mach_msg_type_name_t reply_type, uid_t *uids, mach_msg_type_number_t nuids, gid_t *gids, mach_msg_type_number_t ngids, char *handle, mach_msg_type_number_t handle_len, mach_port_t *file, mach_msg_type_name_t *file_type) { int flags; error_t err; struct node *node; const union diskfs_fhandle *f; struct protid *new_cred; struct peropen *new_po; struct iouser *user; struct port_info *pt = ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class); if (!pt) return EOPNOTSUPP; if (handle_len != sizeof *f) { ports_port_deref (pt); return EINVAL; } f = (const union diskfs_fhandle *) handle; err = diskfs_cached_lookup (f->data.cache_id, &node); if (err) { ports_port_deref (pt); return err; } if (node->dn_stat.st_gen != f->data.gen) { diskfs_nput (node); ports_port_deref (pt); return ESTALE; } err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids); if (err) { diskfs_nput (node); ports_port_deref (pt); return err; } flags = 0; if (! fshelp_access (&node->dn_stat, S_IREAD, user)) flags |= O_READ; if (! fshelp_access (&node->dn_stat, S_IEXEC, user)) flags |= O_EXEC; if (! fshelp_access (&node->dn_stat, S_IWRITE, user) && ! S_ISDIR (node->dn_stat.st_mode) && ! diskfs_check_readonly ()) flags |= O_WRITE; err = diskfs_make_peropen (node, flags, 0, &new_po); if (! err) { err = diskfs_create_protid (new_po, user, &new_cred); if (err) diskfs_release_peropen (new_po); } iohelp_free_iouser (user); diskfs_nput (node); ports_port_deref (pt); if (! err) { *file = ports_get_right (new_cred); *file_type = MACH_MSG_TYPE_MAKE_SEND; } return err; }
/* The user must define this function. Allocate a new node to be of mode MODE in locked directory DP (don't actually set the mode or modify the dir, that will be done by the caller); the user responsible for the request can be identified with CRED. Set *NP to be the newly allocated node. */ error_t diskfs_alloc_node (struct node *dir, mode_t mode, struct node **node) { error_t err; int zone_ptr, nzones = sblock_info->s_n_zones; struct node *np; struct stat *st; ino_t inum; assert (!diskfs_readonly); inum = minixfs_new_inode (); if (inum == 0) return ENOSPC; err = diskfs_cached_lookup (inum, &np); if (err) return err; st = &np->dn_stat; if (st->st_blocks) { st->st_blocks = 0; np->dn_set_ctime = 1; } /* Zero out the zone pointers in case there's some noise left on disk. */ if (sblock_info->s_version == MINIX_V1) { for (zone_ptr = 0; zone_ptr < nzones; zone_ptr++) if (np->dn->info.i_zone_V1[zone_ptr] != 0) { np->dn->info.i_zone_V1[zone_ptr] = 0; np->dn_set_ctime = 1; } } else { for (zone_ptr = 0; zone_ptr < nzones; zone_ptr++) if (np->dn->info.i_zone_V2[zone_ptr] != 0) { np->dn->info.i_zone_V2[zone_ptr] = 0; np->dn_set_ctime = 1; } } /* if (np->dn->info_i_translator != 0) */ /* { */ /* np->dn->info_i_translator = 0; */ /* np->dn_set_ctime = 1; */ /* } */ /* st->st_mode &= ~S_IPTRANS; */ if (np->allocsize) { st->st_size = 0; np->allocsize = 0; np->dn_set_ctime = 1; } st->st_flags = 0; st->st_gen = 0; alloc_sync (np); *node = np; return 0; }