struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) { struct netnode *nn; struct node *np; nn = malloc (sizeof *nn); if (! nn) goto fail; memset (nn, 0, sizeof *nn); nn->ops = ops; nn->hook = hook; np = netfs_make_node (nn); if (! np) goto fail; np->nn = nn; memset (&np->nn_stat, 0, sizeof np->nn_stat); np->nn_translated = 0; if (np->nn->ops->lookup) np->nn_stat.st_mode = S_IFDIR | 0555; else np->nn_stat.st_mode = S_IFREG | 0444; return np; fail: if (ops->cleanup) ops->cleanup (hook); free (nn); return NULL; }
/*Derives a new node from `lnode` and adds a reference to `lnode`*/ error_t node_create (lnode_t * lnode, node_t ** node) { error_t err = 0; /*Create a new netnode */ netnode_t *netnode_new = malloc (sizeof (netnode_t)); /*Reset the memory allocated for the new netnode (just in case :-) ) */ memset (netnode_new, 0, sizeof (netnode_t)); /*If the memory could not be allocated */ if (netnode_new == NULL) err = ENOMEM; else { /*create a new node from the netnode */ node_t *node_new = netfs_make_node (netnode_new); /*If the creation failed */ if (node_new == NULL) { /*set the error code */ err = ENOMEM; /*destroy the netnode created above */ free (netnode_new); /*stop */ return err; } node_new->nn->type = NODE_TYPE_NORMAL; /*link the lnode to the new node */ lnode->node = node_new; /*setup the references in the newly created node */ node_new->nn->lnode = lnode; lnode_ref_add (lnode); /*setup the information in the netnode */ node_new->nn->flags = 0; node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; /*initialize the data fields dealing with positioning this node in the dynamic translator stack */ node_new->nn->dyntrans = NULL; node_new->nn->below = NULL; /*store the result of creation in the second parameter */ *node = node_new; } /*Return the result of operations */ return err; } /*node_create */
/*Creates a proxy (or a shadow) node for the supplied port*/ error_t node_create_from_port (mach_port_t port, node_t ** node) { error_t err = 0; /*Create a new netnode */ netnode_t * netnode_new = malloc (sizeof (netnode_t)); /*Reset the memory allocated for the new netnode (just in case :-) ) */ memset (netnode_new, 0, sizeof (netnode_t)); /*If the memory could not be allocated */ if (netnode_new == NULL) err = ENOMEM; else { /*create a new node from the netnode */ node_t * node_new = netfs_make_node (netnode_new); /*If the creation failed */ if (node_new == NULL) { /*set the error code */ err = ENOMEM; /*destroy the netnode created above */ free (netnode_new); /*stop */ return err; } /*The caller may want to change this to NODE_TYPE_SHADOW if it's the case. */ node_new->nn->type = NODE_TYPE_PROXY; /*this node is ``orphan'' -- it is not associated to any lnode and has some service functions only */ node_new->nn->lnode = NULL; /*setup the information in the netnode */ node_new->nn->flags = 0; node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; node_new->nn->port = port; /*initialize the data fields dealing with positioning this node in the dynamic translator stack */ node_new->nn->dyntrans = NULL; node_new->nn->below = NULL; /*store the result of creation in the second parameter */ *node = node_new; } /*Return the result of operations */ return err; } /*node_create_from_port */
/*Derives a new proxy from `lnode`*/ error_t node_create_proxy (lnode_t * lnode, node_t ** node) { error_t err = 0; /*Create a new netnode */ netnode_t *netnode_new = malloc (sizeof (netnode_t)); /*Reset the memory allocated for the new netnode. We do this here since lnode_add_proxy will try to reference the `lnode` in this netnode and will do bad writes to memory. */ memset (netnode_new, 0, sizeof (netnode_t)); /*If the memory could not be allocated */ if (netnode_new == NULL) err = ENOMEM; else { /*create a new node from the netnode */ node_t *node_new = netfs_make_node (netnode_new); /*If the creation failed */ if (node_new == NULL) { /*set the error code */ err = ENOMEM; /*destroy the netnode created above */ free (netnode_new); /*stop */ return err; } node_new->nn->type = NODE_TYPE_PROXY; /*add this new node to the list of proxies of `lnode` */ lnode_add_proxy (lnode, node_new); /*setup the information in the netnode */ node_new->nn->flags = 0; node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; /*initialize the data fields dealing with positioning this node in the dynamic translator stack */ node_new->nn->dyntrans = NULL; node_new->nn->below = NULL; /*store the result of creation in the second parameter */ *node = node_new; } /*Return the result of operations */ return err; } /*node_create_proxy */
/* Make a new virtual node. Always consumes the ports. */ error_t new_node (struct lnode *ln, struct node **np) { error_t err = 0; struct netnode *nn = calloc (1, sizeof *nn); struct node *node; if (nn == 0) return ENOMEM; node = netfs_make_node (nn); if (node == 0) { free (nn); *np = NULL; return ENOMEM; } if (ln) ln->n = node; nn->ln = ln; *np = node; return err; }
/* cvsfs_make_node * * create a struct node* for the specified netnode 'nn'. */ struct node * cvsfs_make_node(struct netnode *nn) { struct node *node; rwlock_writer_lock(&nn->lock); if(nn->node) { /* there already is a node structure, just return another reference * to this one, instead of wasting memory for yet another one */ mutex_lock(&nn->node->lock); netfs_nref(nn->node); mutex_unlock(&nn->node->lock); rwlock_writer_unlock(&nn->lock); return nn->node; } if(! (node = netfs_make_node(nn))) { rwlock_writer_unlock(&nn->lock); return NULL; } /* put timestamp on file */ fshelp_touch(&node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, cvsfs_maptime); /* initialize stats of new node ... */ node->nn_stat.st_fstype = FSTYPE_MISC; node->nn_stat.st_fsid = stat_template.fsid; node->nn_stat.st_ino = nn->fileno; node->nn_stat.st_mode = stat_template.mode; node->nn_stat.st_nlink = 1; node->nn_stat.st_uid = stat_template.uid; node->nn_stat.st_gid = stat_template.gid; node->nn_stat.st_size = 0; node->nn_stat.st_blksize = 4096; /* is there a better default?? */ node->nn_stat.st_blocks = 0; node->nn_stat.st_author = stat_template.author; if(! nn->revision) { /* we're creating a node for a directory, mark as such! */ node->nn_stat.st_mode |= S_IFDIR; /* since we got a directory we need to supply "executable" * permissions, so our user is enabled to make use of this dir */ if(node->nn_stat.st_mode & S_IRUSR) node->nn_stat.st_mode |= S_IXUSR; if(node->nn_stat.st_mode & S_IRGRP) node->nn_stat.st_mode |= S_IXGRP; if(node->nn_stat.st_mode & S_IROTH) node->nn_stat.st_mode |= S_IXOTH; } else { if(nn->revision->contents && ! config.nostats) { node->nn_stat.st_mode = nn->revision->perm; node->nn_stat.st_size = nn->revision->length; node->nn_stat.st_blocks = (node->nn_stat.st_size >> 9) + 1; node->nn_stat.st_atime = node->nn_stat.st_mtime = node->nn_stat.st_ctime = nn->revision->time; node->nn_stat.st_atime_usec = node->nn_stat.st_mtime_usec = node->nn_stat.st_ctime_usec = 0; } /* well, we're creating a new node for a file ... */ node->nn_stat.st_mode |= S_IFREG; /* for now simply drop all execute permissions, this needs to be fixed, * since CVS support executables, e.g. shell scripts, that we need to * support .... FIXME */ node->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); }
default: return ARGP_ERR_UNKNOWN; } return 0; } struct argp argp = { options, parse_opt, args_doc, doc }; /* Parse our command line arguments. */ argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); netfs_init (); /* Create the root node (some attributes initialized below). */ netfs_root_node = netfs_make_node (&root_nn); if (! netfs_root_node) error (5, ENOMEM, "Cannot create root node"); err = maptime_map (0, 0, &usermux_maptime); if (err) error (6, err, "Cannot map time"); /* Handshake with the party trying to start the translator. */ mux.underlying = netfs_startup (bootstrap, 0); /* We inherit various attributes from the node underlying this translator. */ err = io_stat (mux.underlying, &ul_stat); if (err) error (7, err, "Cannot stat underlying node");