SgObject Sg_AbsolutePath(SgString *path) { char buf[PATH_MAX]; char *ret = realpath(Sg_Utf32sToUtf8s(path), buf); if (ret) { return Sg_Utf8sToUtf32s(buf, strlen(buf)); } if (errno == ENOENT) { /* do some trick here */ if (Sg_AbsolutePathP(path)) return normalise_path(path); return normalise_path(Sg_BuildPath(Sg_CurrentDirectory(), path)); } return SG_FALSE; }
std::string NormalisePath(const std::string &path) { std::string result; result.reserve(path.size()); normalise_path(result, StringRange(path.c_str(), path.size())); return result; }
void split_pathname(std::string const& pathname, std::vector<std::string>& output) { std::istringstream istr(normalise_path(pathname)); std::string token; while (std::getline(istr,token,'/')) output.push_back(token); }
// Calculates the path of target relative to source. std::string compute_relative_path(const std::string& source, const std::string& target) { //std::cerr << "compute_relative_path(a): " << source << " : " << target << std::endl; std::string common_part = normalise_path(source); std::string back; if(common_part.length() > 1 && common_part[common_part.length()-1] == '/') { common_part.erase(common_part.length()-1); } while(boost::iequals(del_substring_front(target, common_part), target)) { size_t offs = common_part.rfind('/'); //std::cerr << "compute_relative_path(b2): " << back << " : " << common_part << std::endl; if(common_part.length() > 1 && offs != std::string::npos) { common_part.erase(offs); back = "../" + back; } else { break; } } common_part = del_substring_front(target, common_part); if(common_part.length() == 1) { common_part = common_part.substr(1); if(back.empty() == false) { back.erase(back.length()-1); } } else if(common_part.length() > 1 && common_part[0] == '/') { common_part = common_part.substr(1); } else { if(back.empty() == false) { back.erase(back.length()-1); } } //std::cerr << "compute_relative_path(b): " << back << " : " << common_part << std::endl; return back + common_part; }
/* Intersect a userpath aperture with a path. Fill rule applied to aperture in NZFILL_TYPE, fill type applied to path is filltype. Note that makeconvex and cliptoall free their argument paths, so only the flattened paths need to be freed */ Bool path_in_path(PATHLIST *appath, PATHLIST *path, int32 filltype, Bool *inside) { PATHINFO apath, fpath ; if ( ! appath || ! path) { /* can't be inside a degenerate path */ *inside = FALSE ; return TRUE ; } /* prepare both paths, using filltype for path and NZFILL for aperture */ fl_setflat( theFlatness( theLineStyle(*gstateptr))) ; if ( ! path_flatten(appath, &apath) || ! normalise_path(&apath, NZFILL_TYPE, FALSE, FALSE) ) return FALSE ; if ( ! thePath(apath) ) { *inside = FALSE ; return TRUE ; } if ( ! path_flatten(path, &fpath) || ! normalise_path(&fpath, filltype, FALSE, FALSE) ) { path_free_list(thePath(apath), mm_pool_temp) ; return FALSE ; } if ( ! thePath(fpath) ) { path_free_list(thePath(apath), mm_pool_temp) ; *inside = FALSE ; return TRUE ; } /* intersect aperture and path */ if ( ! cliptoall(&apath, &fpath, &apath, FALSE) ) return FALSE ; if ( thePath(apath) ) { *inside = TRUE ; /* if it's not degenerate, aperture is painted */ path_free_list(thePath(apath), mm_pool_temp) ; } else *inside = FALSE ; /* if clip is degenerate, it's not inside */ return TRUE ; }
std::string JoinPathBelow(const std::string &base, const std::string &path) { if (base.empty()) return path; if (!path.empty()) { if ((path[0] == '/') && (base != "/")) throw std::invalid_argument(path); else { std::string result(base); result.reserve(result.size() + 1 + path.size()); if (result[result.size()-1] != '/') result += '/'; StringRange rhs(path.c_str(), path.size()); if (path[0] == '/') { assert(base == "/"); ++rhs.begin; } normalise_path(result, rhs); return result; } } else return base; }
std::pair<file_props_ptr,mach_header_props> load_mach_file_props(std::string const& mach_file, std::ifstream& mach, load_props_mach& load_props, std::string& error_message) { if (file_size(mach_file) < 4ULL) { error_message = NOT_MACH_FILE(); return {}; } bool const is_file_in_big_endian = false; // MACH file is stored in big-endian by default. bool const is_it_load_of_root_binary = load_props.root_file() == mach_file; // We read magic number in order to reconse the file type (is it MACH or not). uint8_t num_address_bits = 0U; { uint32_t const magic = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); if (magic == 0xfeedfaceU) // Mach-O 32 bit num_address_bits = 32U; else if (magic == 0xfeedfacfU) // Mach-O 64 bit num_address_bits = 64U; else if (magic == 0xcafebabeU) // FAT binary { error_message = "Mac OS fat binaries are NOT IMPLEMENTED YET!"; return {}; } else { error_message = NOT_MACH_FILE(); return {}; } } // Now we read the rest of the header uint32_t const cpu_type = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); //uint32_t const cpu_subtype = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); skip_bytes(mach,4U); // We ignore cpu-sub-type. if ((num_address_bits == 64U && cpu_type != 0x1000007) || (num_address_bits == 32U && cpu_type != 0x7) ) { error_message = "Unsupported processor architecture."; return {}; } architecture_t const arch = num_address_bits == 32U ? architecture_t::X86_32 : architecture_t::X86_64 ; abi_t const abi = abi_t::DARWIN; platform_ptr const file_platform{ new platform(arch, abi) }; uint32_t const filetype = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); if (filetype != 0x2U && filetype != 0x3U && filetype != 0x6U) { error_message = "The loaded Mach-O file is neither executable nor dynamic library."; return {}; } bool const is_dynamic_library = filetype == 0x3U || filetype == 0x6U; bool const is_fixed_dynamic_library = filetype == 0x3U; uint32_t const num_load_commnads = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); if (num_load_commnads == 0U) { error_message = "There is no load command in the binary."; return {}; } uint32_t const total_num_commnad_bytes = read_bytes_to_int32_t(mach,4U,is_file_in_big_endian); if (total_num_commnad_bytes < num_load_commnads * (num_address_bits / 8U)) { error_message = "The list of load commands is too short."; return {}; } skip_bytes(mach,4ULL); // We ignore flags. if (num_address_bits == 64U) skip_bytes(mach,4ULL); // We skip the reserved word. if ((uint64_t)mach.tellg() + (uint64_t)total_num_commnad_bytes >= (uint64_t)file_size(mach_file)) { error_message = "The list of load commands goes beyond the end of the file."; return {}; } // Next we create file properties data structure and we return results. static uint32_t file_id_generator = 0U; // TODO: This is not an ideal implementation: move it to load_props. file_props_ptr const mach_props { new file_props{ normalise_path(absolute_path(mach_file)), format::MACH(), is_file_in_big_endian, num_address_bits, ++file_id_generator }}; set_file_property(mach_props->property_map(), file_properties::file_type(), is_dynamic_library ? file_types::library() : file_types::executable()); load_props.add_file_props(mach_props); if (is_it_load_of_root_binary) load_props.set_platform( file_platform ); if (*file_platform != *load_props.platform()) { error_message = "Incompatible platforms of the executable and its shared library: " + mach_props->path(); return {}; } return {mach_props,std::make_tuple(num_load_commnads,total_num_commnad_bytes,is_fixed_dynamic_library)}; }
static int do_loadenv(int argc, char *argv[]) { char *filename = NULL, *dirname; unsigned flags = 0; int opt; int scrub = 0; int defaultenv = 0; while ((opt = getopt(argc, argv, "nsd")) > 0) { switch (opt) { case 'n': flags |= ENV_FLAG_NO_OVERWRITE; break; case 's': scrub = 1; break; case 'd': defaultenv = 1; break; default: return COMMAND_ERROR_USAGE; } } if (argc - optind < 2) dirname = "/env"; else dirname = argv[optind + 1]; if (argc - optind < 1) { filename = default_environment_path_get(); } else { char *str = normalise_path(argv[optind]); /* * /dev/defaultenv use to contain the defaultenvironment. * we do not have this file anymore, but maintain compatibility * to the 'loadenv -s /dev/defaultenv' command to restore the * default environment for some time. */ if (!strcmp(str, "/dev/defaultenv")) defaultenv = 1; else filename = argv[optind]; free(str); } if (scrub) { int ret; ret = unlink_recursive(dirname, NULL); if (ret && ret != -ENOENT) { eprintf("cannot remove %s: %s\n", dirname, strerror(-ret)); return 1; } ret = mkdir(dirname, 0); if (ret) { eprintf("cannot create %s: %s\n", dirname, strerror(-ret)); return ret; } } printf("loading environment from %s\n", defaultenv ? "defaultenv" : filename); if (defaultenv) return defaultenv_load(dirname, flags); else return envfs_load(filename, dirname, flags); }
file_props_ptr load_elf_file_props(std::string const& elf_file, std::ifstream& elf, load_props_elf& load_props, std::string& error_message) { if (file_size(elf_file) < 6ULL) { error_message = NOT_ELF_FILE(); return file_props_ptr(); } char magic[4U]; elf.read(magic,4U); if (magic[0] != 0x7F || magic[1] != 'E' || magic[2] != 'L' || magic[3] != 'F' ) { error_message = NOT_ELF_FILE(); return file_props_ptr(); } elf.seekg(0x05ULL); uint8_t endian_mode = ::read_byte(elf); if (endian_mode != 1 && endian_mode != 2) { elf.seekg(0x10ULL); uint32_t const binary_type_little_endian = ::read_bytes_to_uint32_t(elf,2U,false); elf.seekg(0x10ULL); uint32_t const binary_type_big_endian = ::read_bytes_to_uint32_t(elf,2U,true); bool const little_cond = binary_type_little_endian == 2U || binary_type_little_endian == 3U; bool const big_cond = binary_type_big_endian == 2U || binary_type_big_endian == 3U; if (little_cond && !big_cond) { endian_mode = 1U; LOAD_ELF_WARNING_IN( elf_file, "[Header offset 0x05] Unknown type of endian mode (neither little nor big). " "The little endian was deduced form 2 bytes at the offset 0x10." ); } else if (!little_cond && big_cond) { endian_mode = 2U; LOAD_ELF_WARNING_IN( elf_file, "[Header offset 0x05] Unknown type of endian mode (neither little nor big). " "The big endian was deduced form 2 bytes at the offset 0x10." ); } else { error_message = "[Header offset 0x05] Unknown type of endian mode (neither little nor big)."; return file_props_ptr(); } } bool const is_file_in_big_endian = endian_mode == 1 ? false : true; elf.seekg(0x04ULL); uint8_t address_mode = ::read_byte(elf); if (address_mode != 1 && address_mode != 2) { elf.seekg(0x1CULL); uint32_t const phd_offset_32 = ::read_bytes_to_uint32_t(elf,4U,is_file_in_big_endian); uint64_t const phd_offset_64 = ::read_bytes_to_uint64_t(elf,8U,is_file_in_big_endian); bool const cond32 = phd_offset_32 != 0U && phd_offset_32 < file_size(elf_file); bool const cond64 = phd_offset_64 != 0U && phd_offset_64 < file_size(elf_file); if (cond32 && !cond64) { address_mode = 1U; LOAD_ELF_WARNING_IN( elf_file, "[Header offset 0x04] Unknown type for address mode (neither 32- nor 64-bit). " "The 32-bit address mode was deduced form the 12 bytes at the offset 0x1c." ); } else if (!cond32 && cond64) { address_mode = 2U; LOAD_ELF_WARNING_IN( elf_file, "[Header offset 0x04] Unknown type for address mode (neither 32- nor 64-bit). " "The 64-bit address mode was deduced form the 12 bytes at the offset 0x1c." ); } else { error_message = "[ELF][Header offset 0x04] Unknown type for address mode (neither 32- nor 64-bit)."; return file_props_ptr(); } } bool const file_uses_32_bit_addresses = address_mode == 1 ? true : false; elf.seekg(0x06ULL); file_props_ptr const elf_props{ new file_props{ normalise_path(absolute_path(elf_file)), format::ELF(), is_file_in_big_endian, (uint8_t)(file_uses_32_bit_addresses ? 32U : 64U), load_props.get_fresh_file_id() }}; set_file_property(elf_props->property_map(), file_properties::abi_loader(), abi_loaders::NONE()); return elf_props; }
int ls(const char *path, ulong flags) { DIR *dir; struct dirent *d; char tmp[PATH_MAX]; struct stat s; struct string_list sl; string_list_init(&sl); if (stat(path, &s)) return errno; if (flags & LS_SHOWARG && s.st_mode & S_IFDIR) printf("%s:\n", path); if (!(s.st_mode & S_IFDIR)) { ls_one(path, &s); return 0; } dir = opendir(path); if (!dir) return errno; while ((d = readdir(dir))) { sprintf(tmp, "%s/%s", path, d->d_name); if (stat(tmp, &s)) goto out; if (flags & LS_COLUMN) string_list_add_sorted(&sl, d->d_name); else ls_one(d->d_name, &s); } closedir(dir); if (flags & LS_COLUMN) { string_list_print_by_column(&sl); string_list_free(&sl); } if (!(flags & LS_RECURSIVE)) return 0; dir = opendir(path); if (!dir) { errno = -ENOENT; return -ENOENT; } while ((d = readdir(dir))) { if (!strcmp(d->d_name, ".")) continue; if (!strcmp(d->d_name, "..")) continue; sprintf(tmp, "%s/%s", path, d->d_name); if (stat(tmp, &s)) goto out; if (s.st_mode & S_IFDIR) { char *norm = normalise_path(tmp); ls(norm, flags); free(norm); } } out: closedir(dir); return 0; }