prmap_t * proc_name2map(struct proc_handle *p, const char *name) { size_t i; int cnt; prmap_t *map; char tmppath[MAXPATHLEN]; struct kinfo_vmentry *kves, *kve; rd_loadobj_t *rdl; /* * If we haven't iterated over the list of loaded objects, * librtld_db isn't yet initialized and it's very likely * that librtld_db called us. We need to do the heavy * lifting here to find the symbol librtld_db is looking for. */ if (p->nobjs == 0) { if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) return (NULL); for (i = 0; i < (size_t)cnt; i++) { kve = kves + i; basename_r(kve->kve_path, tmppath); if (strcmp(tmppath, name) == 0) { map = proc_addr2map(p, kve->kve_start); free(kves); return (map); } } free(kves); return (NULL); } if (name == NULL || strcmp(name, "a.out") == 0) { map = proc_addr2map(p, p->rdobjs[0].rdl_saddr); return (map); } for (i = 0; i < p->nobjs; i++) { rdl = &p->rdobjs[i]; basename_r(rdl->rdl_path, tmppath); if (strcmp(tmppath, name) == 0) { if ((map = malloc(sizeof(*map))) == NULL) return (NULL); proc_rdl2prmap(rdl, map); return (map); } } return (NULL); }
prmap_t * proc_obj2map(struct proc_handle *p, const char *objname) { size_t i; prmap_t *map; rd_loadobj_t *rdl; char path[MAXPATHLEN]; rdl = NULL; for (i = 0; i < p->nobjs; i++) { basename_r(p->rdobjs[i].rdl_path, path); if (strcmp(path, objname) == 0) { rdl = &p->rdobjs[i]; break; } } if (rdl == NULL) { if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL) rdl = p->rdexec; else return (NULL); } if ((map = malloc(sizeof(*map))) == NULL) return (NULL); proc_rdl2prmap(rdl, map); return (map); }
static const char * swap_on_off(const char *name, int doingall, char *mntops) { char base[PATH_MAX]; /* Swap on vnode-backed md(4) device. */ if (mntops != NULL && (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || strncmp(_PATH_DEV MD_NAME, name, sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) return (swap_on_off_md(name, mntops, doingall)); basename_r(name, base); /* Swap on encrypted device by GEOM_BDE. */ if (fnmatch("*.bde", base, 0) == 0) return (swap_on_off_gbde(name, doingall)); /* Swap on encrypted device by GEOM_ELI. */ if (fnmatch("*.eli", base, 0) == 0) return (swap_on_off_geli(name, mntops, doingall)); /* Swap on special file. */ return (swap_on_off_sfile(name, doingall)); }
int main(int argc, char *argv[]) { if (!*argv) return 127; // Snapshot stack location so we can detect recursion depth later. // This is its own block so probe doesn't permanently consume stack. else { int stack; toys.stacktop = &stack; } *argv = basename_r(*argv); // If nommu can't fork, special reentry path. // Use !stacktop to signal "vfork happened", both before and after xexec() if (!CFG_TOYBOX_FORK) { if (0x80 & **argv) { **argv &= 0x7f; toys.stacktop = 0; } } if (CFG_TOYBOX) { // Call the multiplexer, adjusting this argv[] to be its' argv[1]. // (It will adjust it back before calling toy_exec().) toys.argv = argv-1; toybox_main(); } else { // a single toybox command built standalone with no multiplexer toy_singleinit(toy_list, argv); toy_list->toy_main(); } xexit(); }
int proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd) { size_t i; rd_loadobj_t *rdl; prmap_t map; char path[MAXPATHLEN]; char last[MAXPATHLEN]; if (p->nobjs == 0) return (-1); memset(last, 0, sizeof(last)); for (i = 0; i < p->nobjs; i++) { rdl = &p->rdobjs[i]; proc_rdl2prmap(rdl, &map); basename_r(rdl->rdl_path, path); /* * We shouldn't call the callback twice with the same object. * To do that we are assuming the fact that if there are * repeated object names (i.e. different mappings for the * same object) they occur next to each other. */ if (strcmp(path, last) == 0) continue; (*func)(cd, &map, path); strlcpy(last, path, sizeof(last)); } return (0); }
static void TestBasename(const char* in, const char* expected_out, int expected_rc, char* buf, size_t buf_size, int expected_errno) { errno = 0; int rc = basename_r(in, buf, buf_size); ASSERT_EQ(expected_rc, rc) << in; if (rc != -1 && buf != NULL) { ASSERT_STREQ(expected_out, buf) << in; } ASSERT_EQ(expected_errno, errno) << in; }
char * basename(const char *path) { static char *bname = NULL; if (bname == NULL) { bname = (char *)malloc(MAXPATHLEN); if (bname == NULL) return (NULL); } return (basename_r(path, bname)); }
/* * Wait for the specified process to hit a breakpoint at the specified symbol. */ static void verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname, const char *mapname) { char mapbname[MAXPATHLEN], *name; GElf_Sym tsym; prmap_t *map; size_t namesz; u_long addr; int error, state; state = proc_wstatus(phdl); ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state); /* Get the program counter and decrement it. */ error = proc_regget(phdl, REG_PC, &addr); ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'", target_prog_file); proc_bkptregadj(&addr); /* * Make sure the PC matches the expected value obtained from the symbol * definition we looked up earlier. */ ATF_CHECK_EQ_MSG(addr, sym->st_value, "program counter 0x%lx doesn't match expected value 0x%jx", addr, (uintmax_t)sym->st_value); /* * Ensure we can look up the r_debug_state symbol using its starting * address and that the resulting symbol matches the one we found using * a name lookup. */ namesz = strlen(symname) + 1; name = malloc(namesz); ATF_REQUIRE(name != NULL); error = proc_addr2sym(phdl, addr, name, namesz, &tsym); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr); ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0); ATF_REQUIRE_EQ_MSG(strcmp(symname, name), 0, "expected symbol name '%s' doesn't match '%s'", symname, name); free(name); map = proc_addr2map(phdl, addr); ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx", addr); basename_r(map->pr_mapname, mapbname); ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0, "expected map name '%s' doesn't match '%s'", mapname, mapbname); }
static void uv__inotify_read(EV_P_ ev_io* w, int revents) { const struct inotify_event* e; uv_fs_event_t* handle; uv_loop_t* uv_loop; const char* filename; ssize_t size; int events; const char *p; /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */ char buf[4096]; uv_loop = container_of(w, uv_loop_t, inotify_read_watcher); while (1) { do { size = read(uv_loop->inotify_fd, buf, sizeof buf); } while (size == -1 && errno == EINTR); if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { e = (const struct inotify_event*)p; events = 0; if (e->mask & (IN_ATTRIB|IN_MODIFY)) events |= UV_CHANGE; if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) events |= UV_RENAME; handle = find_watcher(uv_loop, e->wd); if (handle == NULL) continue; /* Handle has already been closed. */ /* inotify does not return the filename when monitoring a single file * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ filename = e->len ? (const char*) (e + 1) : basename_r(handle->filename); handle->cb(handle, filename, events, 0); } } }
char * basename (const char *path) { static char *bname = NULL; if (bname == NULL) { bname = (char *) malloc (PATH_MAX); if (bname == NULL) return (NULL); } return (basename_r (path, bname, PATH_MAX) < 0) ? NULL : bname; }
static const char * swap_on_off( const char *name, int doingall, char *mntops ) { char base[PATH_MAX]; if ( mntops != NULL && (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || strncmp(_PATH_DEV MD_NAME, name, sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0) ) return ( swap_on_off_md( name, mntops, doingall ) ); basename_r( name, base ); if ( fnmatch( "*.bde", base, 0 ) == 0 ) return ( swap_on_off_gbde( name, doingall ) ); if ( fnmatch( "*.eli", base, 0 ) == 0 ) return ( swap_on_off_geli( name, mntops, doingall ) ); return ( swap_on_off_sfile( name, doingall ) ); }
prmap_t * proc_obj2map(struct proc_handle *p, const char *objname) { size_t i; prmap_t *map; rd_loadobj_t *rdl; char path[MAXPATHLEN]; for (i = 0; i < p->nobjs; i++) { rdl = &p->rdobjs[i]; basename_r(rdl->rdl_path, path); if (strcmp(path, objname) == 0) { if ((map = malloc(sizeof(*map))) == NULL) return (NULL); proc_rdl2prmap(rdl, map); return (map); } } return (NULL); }
char* basename(const char* path) { char* buf = g_basename_tls_buffer.get(); int rc = basename_r(path, buf, g_basename_tls_buffer.size()); return (rc < 0) ? NULL : buf; }
int move_file(const char *source, const char *target) { char *cmmd; char *tfile, inptarget[256], fulltarget[256]; struct stat buf; short fAgain = 1; /* test target; append basename of source & test again */ int source_size, target_size; char basename_buf[256]; char dirname_buf[256]; strcpy(inptarget,target); tfile = inptarget; /* Check if source file is accessible */ if(access(source, R_OK)) { /* source does NOT exist */ return(FAILURE); } if((source_size = get_file_size(source)) < 0) { /* cannot stat source file */ return(FAILURE); } /* Check if source directory has proper permissions */ strcpy(fulltarget, dirname_r1(source, dirname_buf)); if(access(fulltarget, R_OK + W_OK + X_OK)) { /* permissions on source dir will not allow move */ return(FAILURE); } TRY_AGAIN: if(! access(tfile, F_OK)) { /* tfile exists */ stat(tfile, &buf); if(S_ISREG(buf.st_mode)) { /* tfile exists and is regular file, delete it */ if(unlink(tfile) < 0) { return(FAILURE); /* permission to delete tfile denied */ } } else if(fAgain) { if(S_ISDIR(buf.st_mode)) { /* tfile exists and is directory, test permission & append filename */ if(access(tfile,R_OK + W_OK + X_OK)) { return(FAILURE); /* rwx permission to target dir denied */ } /* append basename of source to target directory name */ sprintf(fulltarget,"%s/%s", target, basename_r(source,basename_buf)); tfile = fulltarget; fAgain = 0; /* FALSE, don't allow directory test again */ goto TRY_AGAIN; } else { /* not reg file and not directory, unknown file type */ return(FAILURE); } } else { /* fAgain false, target is directory, after appending basename */ /* from source, we have name of existing non-regular file. ERROR */ return(FAILURE); } } /* At this point, tfile points to non-existing file */ if(link(source, tfile) < 0) { if(errno == EXDEV) { /* attempted cross-device (filesystem) link, use 'mv' instead. */ if((cmmd = (char *)malloc(1024)) == NULL) { return(FAILURE); /* cannot allocate memory for cmmd line. */ } sprintf(cmmd,"mv %s %s", source, target); if(system(cmmd) < 0) { /* system call failed, this says NOTHING about mv command. */ if(errno == EINTR) { sleep(15); /* caught interrupt, cmmd may still be executing */ } else { /* system call failed */ free(cmmd); return(FAILURE); } } free(cmmd); } else { return(FAILURE); /* link failure */ } } /* At this point, link or system("mv...") (move) claims to have succeeded.*/ if(access(tfile, F_OK)) { return(FAILURE); /* Target file (tfile) no exist! */ } if((target_size = get_file_size(tfile)) < 0) { /* Cannot stat target file for which access just above succeeded. ** If source still exists, unlink tfile and return FAILURE. ** If source no longer exists (i.e., corrupted mv command above), ** then return SUCCESS. In this case, tfile exists and is ** accessible. We can't return failure because source no longer ** exists. Best we can do is return success and let caller ** have access to the tfile (target). */ if(access(source, F_OK)) { unlink(tfile); return(FAILURE); } target_size = 0; } if((target_size) && (target_size != source_size)) { /* After successful move we find that the size of the original ** source file is not the same as the size of the new tfile ** (target)! If source still exists, unlink tfile and return ** FAILURE. If source does not exist, we can only return SUCCESS. ** In this case, tfile exists and is accessible. */ if(access(source, F_OK)) { unlink(tfile); return(FAILURE); } } /* Link succeeded, target now exists with hopefully the correct ** size, now delete source. For system("mv") source will no longer ** exist. Since source is scratch/work file, don't care if problem ** deleting it. */ unlink(source); /* File successfully moved */ return(SUCCESS); }
int CopyFileToFile(const char *source, const char *target) { char *p; char targetpath[256]; int fdOut; int status = 1; /* positive number -> SUCCESS */ struct stat buf; int source_size, target_size; char basename_buf[256]; char dirname_buf[256]; /* Verify that source exists and we can read it and it is a ** regular file. */ if(access(source, R_OK)) { return(-1); /* source either not exist or is not readable */ } if(stat(source, &buf) < 0) { return(-1); /* cannot stat source file */ } if( ! S_ISREG(buf.st_mode)) { /* source exists, but is NOT a regular file. Cannot copy */ return(-1); } /* Check if target is a file or directory. If a directory, get basename ** from source to determine full path of target FILE name. */ if(stat(target, &buf) < 0) { if(errno != ENOENT) { return(-7); /* cannot stat target file or directory */ } /* else, stat failed because target does not exist. Assumption is ** that target is pathname of target FILE. Check if directory (..) ** has proper permissions. */ p = dirname_r1(target, dirname_buf); /* directory, i.e., target/.. */ if(access(p, R_OK + W_OK + X_OK)) { return(-7); /* insufficient perms to create new file in target dir */ } /* Target not yet exist, and directory it is to be in has proper ** permissions. okay to continue. */ strcpy(targetpath, target); } else if(S_ISDIR(buf.st_mode)) { /* target exists and is directory. check permissions and determine ** target filename. */ if(access(target, R_OK + W_OK + X_OK)) { return(-7); /* insufficient perms to create new file in target dir */ } p = basename_r(source, basename_buf); sprintf(targetpath, "%s/%s", target, p); } else if( ! S_ISREG(buf.st_mode)) { /* Target exists, but is not a directory and is not a regular file. ** Cannot copy (use CopyFileToFD / CopyFDToFile for tape operations). */ return(-7); } else { /* Target is name of existing regular file. */ strcpy(targetpath, target); } /* Now if targetpath exists, do we have permission to overwrite it? */ if( ! access(targetpath, F_OK)) { /* targetpath exists */ if(access(targetpath, W_OK)) { /* targetpath exists, but we don't have write access! */ return(-7); } /* else, targetpath exists and we do have write access */ } /* else, targetpath no exist yet; okay since we will create it */ /* Open target file */ if((fdOut = open(targetpath, O_RDWR | O_CREAT | O_TRUNC, PERM_0664)) < 0) { return(-7); } /* CopyFileToFD() will open source file */ status = CopyFileToFD(source, fdOut, COPY_BLOCKSIZE); /* Check size of both source and target. If not same, copy failed. */ if((source_size = get_file_size(source)) < 0) { status = -1; } else if((target_size = get_file_size(targetpath)) < 0) { status = -7; } else if(source_size != target_size) { /* copy appears to have succeeded, but target file is not same ** size as source file. Consider this a failure. */ status = -8; } close(fdOut); if(status < 0) unlink(targetpath); return(status); }
int sandbox_class_new(const char *path, size_t maxmaplen, struct sandbox_class **sbcpp) { char sandbox_basename[MAXPATHLEN]; struct sandbox_class *sbcp; struct sandbox_class **new_sandbox_classes; int fd, saved_errno; size_t i; fd = open(path, O_RDONLY); if (fd == -1) { saved_errno = errno; warn("%s: open %s", __func__, path); errno = saved_errno; return (-1); } sbcp = calloc(1, sizeof(*sbcp)); if (sbcp == NULL) { saved_errno = errno; warn("%s: malloc", __func__); close(fd); errno = saved_errno; return (-1); } sbcp->sbc_fd = fd; sbcp->sbc_path = strdup(path); if (sbcp->sbc_path == NULL) { saved_errno = errno; warn("%s: fstat %s", __func__, path); goto error; } if (fstat(sbcp->sbc_fd, &sbcp->sbc_stat) < 0) { saved_errno = errno; warn("%s: fstat %s", __func__, path); goto error; } /* * Parse the ELF and produce mappings for code and data. */ if ((sbcp->sbc_codemap = sandbox_parse_elf64(fd, SANDBOX_LOADELF_CODE)) == NULL) { saved_errno = EINVAL; warnx("%s: sandbox_parse_elf64(CODE) failed for %s", __func__, path); goto error; } if ((sbcp->sbc_datamap = sandbox_parse_elf64(fd, SANDBOX_LOADELF_DATA)) == NULL) { saved_errno = EINVAL; warnx("%s: sandbox_parse_elf64(DATA) failed for %s", __func__, path); goto error; } /* * Don't allow sandbox binaries to request over maxmaplen of * either code or data. * * XXXBD: It would be nice to have some sort of default sane * value, but programs can have astonishing amounts of BSS * relative to file size. */ if (maxmaplen > 0 && sandbox_map_maxoffset(sbcp->sbc_codemap) > maxmaplen) { saved_errno = EINVAL; warnx("%s: %s code too large", __func__, path); goto error; } if (maxmaplen > 0 && sandbox_map_maxoffset(sbcp->sbc_datamap) > maxmaplen) { saved_errno = EINVAL; warnx("%s: %s data too large", __func__, path); goto error; } /* * Initialise the class mapping: this will be the code capabilty used * by all sandboxes. For now, we just map the code segment in exactly * the same way we do the data segment. In the future, we will want * to initialise them differently. */ if (sandbox_class_load(sbcp) < 0) { saved_errno = EINVAL; warnx("%s: sandbox_class_load() failed for %s", __func__, path); goto error; } /* * Resolve methods in other classes. */ for (i = 0; i < num_sandbox_classes; i++) { /* XXXBD: Check there are no conflicting class names */ if (sandbox_resolve_methods(sbcp->sbc_provided_classes, sandbox_classes[i]->sbc_required_methods) < 0) { saved_errno = EINVAL; warnx("%s: sandbox_resolve_methods() failed providing " "methods from %s to %s", __func__, path, sandbox_classes[i]->sbc_path); goto error; } if (sandbox_resolve_methods( sandbox_classes[i]->sbc_provided_classes, sbcp->sbc_required_methods) < 0) { saved_errno = EINVAL; warnx("%s: sandbox_resolve_methods() failed providing " "methods from %s to %s", __func__, sandbox_classes[i]->sbc_path, path); goto error; } } /* * XXXBD: failure to initalize main_*_methods should eventually * be impossible and trigger an assert. */ if (main_provided_classes != NULL && main_required_methods != NULL) { if (sandbox_resolve_methods(sbcp->sbc_provided_classes, main_required_methods) < 0) { saved_errno = EINVAL; warnx("%s: sandbox_resolve_methods() failed providing " "methods from %s main program", __func__, path); goto error; } if (sandbox_resolve_methods(main_provided_classes, sbcp->sbc_required_methods) < 0) { saved_errno = EINVAL; warnx("%s: sandbox_resolve_methods() failed providing " "methods from main program to %s", __func__, path); goto error; } } /* * Update main program method variables. * * XXXBD: Doing this in every class is inefficient. */ if (sandbox_set_required_method_variables(cheri_getdefault(), main_required_methods) == -1) { warnx("%s: sandbox_set_required_method_variables for main " "program", __func__); return (-1); } /* * Register the class on the list of classes. */ if (max_sandbox_classes == 0) { max_sandbox_classes = 4; if ((sandbox_classes = calloc(max_sandbox_classes, sizeof(*sandbox_classes))) == NULL) { saved_errno = errno; warn("%s: calloc sandbox_classes array", __func__); goto error; } } if (num_sandbox_classes >= max_sandbox_classes) { if ((new_sandbox_classes = realloc(sandbox_classes, max_sandbox_classes * 2 * sizeof(*sandbox_classes))) == NULL) { saved_errno = errno; warn("%s: realloc sandbox_classes array", __func__); goto error; } free(sandbox_classes); sandbox_classes = new_sandbox_classes; max_sandbox_classes *= 2; } sandbox_classes[num_sandbox_classes++] = sbcp; /* * Register the class/object for statistics; also register a single * "noname" method to catch statistics for unnamed or overflow * methods. * * NB: We use the base address of the sandbox's $c0 as the 'name' of * the object, since this is most useful for comparison to capability * values. However, you could also see an argument for using 'sb' * itself here. */ (void)sandbox_stat_class_register(&sbcp->sbc_sandbox_class_statp, basename_r(path, sandbox_basename)); (void)sandbox_stat_method_register(&sbcp->sbc_sandbox_method_nonamep, sbcp->sbc_sandbox_class_statp, "<noname>"); *sbcpp = sbcp; return (0); error: if (sbcp->sbc_path != NULL) free(sbcp->sbc_path); close(sbcp->sbc_fd); free(sbcp); errno = saved_errno; return (-1); }
char * get_suggested_filename (char *src, char *dst_ext) { char *tmp = NULL; char *base = NULL; char *dir_name = NULL; #ifdef __APPLE__ char bname[FILENAME_MAX]; char dname[FILENAME_MAX]; #else char saved[FILENAME_MAX]; int copylen; #endif char *ext = NULL; int len = FILENAME_MAX; if (!src) { printf("[%s] Invalid argument.\n", __FUNCTION__); return tmp_name; } if (!dst_ext) dst_ext = dfl_ext; #ifdef __APPLE__ base = basename_r(src, bname); dir_name = dirname_r (src, dname); #else copylen = strlen(src); if (copylen >= FILENAME_MAX) copylen = FILENAME_MAX-1; strncpy (saved, src, copylen); saved[copylen] = '\0'; base = basename(saved); dir_name = dirname (saved); #endif ext = get_extension(src); NIL_DEBUG("Dirname: %s\n", dir_name); NIL_DEBUG("Basename: %s\n", base); NIL_DEBUG("Extension: %s\n", ext?ext:"(nil)"); NIL_DEBUG("Remove extenstion [%s] --> ", base); tmp = strrchr(base, '.'); if (tmp) { *tmp = 0x00; NIL_DEBUG("[%s]: changed\n", base); } else { NIL_DEBUG("[%s]: Not changed.\n", base); } tmp = (char *)malloc(FILENAME_MAX); if (tmp) { int i = 0; snprintf (tmp,FILENAME_MAX,"%s/%s.%s",dir_name, base, dst_ext); NIL_DEBUG ("Temporary Filename: %s\n", tmp); while (existFile(tmp)){ snprintf (tmp,len,"%s/%s_%d.%s",dir_name, base, i, dst_ext); NIL_DEBUG ("Temporary Filename: %s\n", tmp); i++; } } else { tmp = tmp_name; } #if 0 { char *p = dir_name; p += strlen(dir_name); printf ("%p(p+strlen) %p(base) \n", p, base); if ( base == p+1 ){ *p = '/'; } } #endif return tmp; }