static int binfs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { int index; finfo("Open '%s'\n", relpath); /* BINFS is read-only. Any attempt to open with any kind of write * access is not permitted. */ if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) { ferr("ERROR: Only O_RDONLY supported\n"); return -EACCES; } /* Check if the an entry exists with this name in the root directory. * so the 'relpath' must be the name of the builtin function. */ index = builtin_isavail(relpath); if (index < 0) { ferr("ERROR: Builting %s does not exist\n", relpath); return -ENOENT; } /* Save the index as the open-specific state in filep->f_priv */ filep->f_priv = (FAR void *)((uintptr_t)index); return OK; }
static int builtin_loadbinary(struct binary_s *binp) { FAR const char *filename; FAR const struct builtin_s *b; int fd; int index; int ret; binfo("Loading file: %s\n", binp->filename); /* Open the binary file for reading (only) */ fd = open(binp->filename, O_RDONLY); if (fd < 0) { int errval = get_errno(); berr("ERROR: Failed to open binary %s: %d\n", binp->filename, errval); return -errval; } /* If this file is a BINFS file system, then we can recover the name of * the file using the FIOC_FILENAME ioctl() call. */ ret = ioctl(fd, FIOC_FILENAME, (unsigned long)((uintptr_t)&filename)); if (ret < 0) { int errval = get_errno(); berr("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval); close(fd); return -errval; } /* Other file systems may also support FIOC_FILENAME, so the real proof * is that we can look up the index to this name in g_builtins[]. */ index = builtin_isavail(filename); if (index < 0) { int errval = get_errno(); berr("ERROR: %s is not a builtin application\n", filename); close(fd); return -errval; } /* Return the load information. NOTE: that there is no way to configure * the priority. That is a bug and needs to be fixed. */ b = builtin_for_index(index); binp->entrypt = b->main; binp->stacksize = b->stacksize; binp->priority = b->priority; close(fd); return OK; }
int exec_builtin(FAR const char *appname, FAR char * const *argv, FAR const char *redirfile, int oflags) { FAR const struct builtin_s *builtin; posix_spawnattr_t attr; posix_spawn_file_actions_t file_actions; struct sched_param param; pid_t pid; int index; int ret; /* Verify that an application with this name exists */ index = builtin_isavail(appname); if (index < 0) { ret = ENOENT; goto errout_with_errno; } /* Get information about the builtin */ builtin = builtin_for_index(index); if (builtin == NULL) { ret = ENOENT; goto errout_with_errno; } /* Initialize attributes for task_spawn(). */ ret = posix_spawnattr_init(&attr); if (ret != 0) { goto errout_with_errno; } ret = posix_spawn_file_actions_init(&file_actions); if (ret != 0) { goto errout_with_attrs; } /* Set the correct task size and priority */ param.sched_priority = builtin->priority; ret = posix_spawnattr_setschedparam(&attr, ¶m); if (ret != 0) { goto errout_with_actions; } ret = task_spawnattr_setstacksize(&attr, builtin->stacksize); if (ret != 0) { goto errout_with_actions; } /* If robin robin scheduling is enabled, then set the scheduling policy * of the new task to SCHED_RR before it has a chance to run. */ #if CONFIG_RR_INTERVAL > 0 ret = posix_spawnattr_setschedpolicy(&attr, SCHED_RR); if (ret != 0) { goto errout_with_actions; } ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER); if (ret != 0) { goto errout_with_actions; } #else ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDPARAM); if (ret != 0) { goto errout_with_actions; } #endif /* Is output being redirected? */ if (redirfile) { /* Set up to close open redirfile and set to stdout (1) */ ret = posix_spawn_file_actions_addopen(&file_actions, 1, redirfile, O_WRONLY, 0644); if (ret != 0) { sdbg("ERROR: posix_spawn_file_actions_addopen failed: %d\n", ret); goto errout_with_actions; } } /* Start the built-in */ ret = task_spawn(&pid, builtin->name, builtin->main, &file_actions, &attr, (argv) ? &argv[1] : (FAR char * const *)NULL, (FAR char * const *)NULL); if (ret != 0) { sdbg("ERROR: task_spawn failed: %d\n", ret); goto errout_with_actions; } /* Free attibutes and file actions. Ignoring return values in the case * of an error. */ /* Return the task ID of the new task if the task was sucessfully * started. Otherwise, ret will be ERROR (and the errno value will * be set appropriately). */ (void)posix_spawn_file_actions_destroy(&file_actions); (void)posix_spawnattr_destroy(&attr); return pid; errout_with_actions: (void)posix_spawn_file_actions_destroy(&file_actions); errout_with_attrs: (void)posix_spawnattr_destroy(&attr); errout_with_errno: set_errno(ret); return ERROR; }