diff --git a/CMakeLists.txt b/CMakeLists.txt index 0824baa..4761a8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,10 @@ elseif (CMAKE_C_COMPILER_ID STREQUAL "MSVC") add_compile_options(${win_cflags}) endif() +link_libraries(curl) +if (WIN32) + link_libraries(shlwapi) +endif () add_subdirectory(src) set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}") diff --git a/examples/template/example.ini b/examples/template/example.ini index e84cf67..3419727 100644 --- a/examples/template/example.ini +++ b/examples/template/example.ini @@ -1,53 +1,53 @@ -[meta] -; (string) Mission type: hst, jwst -mission = - -; (string) Name of delivery -name = - -; (string) A codename is only used when mission is set to "hst" -codename = - -; (string) Version of the delivery -version = - -; (string) Release Candidate of delivery. -; NOTE: Ignored when final is true. -rc = - -; (boolean) Enable delivery finalization routines -final = - -; (string) URL of Conda environment YAML -; NOTE: Generally the final release of a older delivery -based_on = - -; (string) Target version of Python -python = - -[conda] -installer_name = Miniforge3 -installer_version = 23.3.1-1 -installer_platform = ${OMC_CONDA_PLATFORM} -installer_arch = ${OMC_CONDA_ARCH} -installer_baseurl = https://github.com/conda-forge/miniforge/releases/latest/download - -; (list) Conda packages to install -conda_packages = - -; (list) Python packages to install -pip_packages = - -[runtime] -; (string) Environment variable key pairs -; key=value - -[test:name] ; where test:"name" denotes the package name -; (string) Version of tested package -version = - -; (string) Git repository of tested package -repository = - -; (list) Commands to execute against tested package -script = +[meta] +; (string) Mission type: hst, jwst +mission = + +; (string) Name of delivery +name = + +; (string) A codename is only used when mission is set to "hst" +codename = + +; (string) Version of the delivery +version = + +; (string) Release Candidate of delivery. +; NOTE: Ignored when final is true. +rc = + +; (boolean) Enable delivery finalization routines +final = + +; (string) URL of Conda environment YAML +; NOTE: Generally the final release of a older delivery +based_on = + +; (string) Target version of Python +python = + +[conda] +installer_name = Miniforge3 +installer_version = 23.3.1-1 +installer_platform = ${OMC_CONDA_PLATFORM} +installer_arch = ${OMC_CONDA_ARCH} +installer_baseurl = https://github.com/conda-forge/miniforge/releases/latest/download + +; (list) Conda packages to install +conda_packages = + +; (list) Python packages to install +pip_packages = + +[runtime] +; (string) Environment variable key pairs +; key=value + +[test:name] ; where test:"name" denotes the package name +; (string) Version of tested package +version = + +; (string) Git repository of tested package +repository = + +; (list) Commands to execute against tested package +script = diff --git a/include/config.h.in b/include/config.h.in index fe6beb2..3c980b0 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -5,6 +5,7 @@ #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) #define OMC_OS_WINDOWS +#include "os_windows.h" #elif defined(__linux__) #define OMC_OS_LINUX diff --git a/include/deliverable.h b/include/deliverable.h index effd098..f9fb364 100644 --- a/include/deliverable.h +++ b/include/deliverable.h @@ -6,7 +6,7 @@ #include #include #include -#include + #include "omc.h" #define DELIVERY_PLATFORM_MAX 4 @@ -139,7 +139,7 @@ struct Delivery { * \brief Global runtime variables */ struct Runtime { - RuntimeEnv *environ; ///< Environment variables + struct StrList *env; ///< Environment variables } runtime; /*! \struct Test diff --git a/include/environment.h b/include/environment.h index 484f02c..a7e6604 100644 --- a/include/environment.h +++ b/include/environment.h @@ -7,7 +7,7 @@ #include #include #include -#include "environment.h" +#include "omc.h" typedef struct StrList RuntimeEnv; @@ -20,4 +20,5 @@ char *runtime_expand_var(RuntimeEnv *env, char *input); void runtime_export(RuntimeEnv *env, char **keys); void runtime_apply(RuntimeEnv *env); void runtime_free(RuntimeEnv *env); + #endif //OMC_ENVIRONMENT_H diff --git a/include/ini.h b/include/ini.h index fa2bd98..6e445e2 100644 --- a/include/ini.h +++ b/include/ini.h @@ -101,11 +101,11 @@ struct INIFILE *ini_open(const char *filename); struct INISection *ini_section_search(struct INIFILE **ini, unsigned mode, char *value); /** - * - * @param ini - * @param section - * @param key - * @return + * + * @param ini + * @param section + * @param key + * @return */ int ini_has_key(struct INIFILE *ini, const char *section, const char *key); diff --git a/include/omc.h b/include/omc.h index a116296..c5b3f30 100644 --- a/include/omc.h +++ b/include/omc.h @@ -8,37 +8,37 @@ #include #include #include -#include +#include "config.h" #define SYSERROR(MSG, ...) do { \ fprintf(stderr, "%s:%s:%d:%s - ", path_basename(__FILE__), __FUNCTION__, __LINE__, strerror(errno) ? "info" : strerror(errno)); \ fprintf(stderr, MSG LINE_SEP, __VA_ARGS__); \ } while (0) + #define OMC_BUFSIZ 8192 #define OMC_NAME_MAX 255 #define OMC_DIRSTACK_MAX 1024 #define OMC_TIME_STR_MAX 128 #define HTTP_ERROR(X) X >= 400 -#include "config.h" #include "template.h" +#include "strlist.h" +#include "str.h" +#include "environment.h" #include "utils.h" #include "copy.h" #include "ini.h" #include "conda.h" -#include "environment.h" #include "artifactory.h" #include "docker.h" -#include "deliverable.h" -#include "str.h" -#include "strlist.h" #include "system.h" #include "download.h" #include "recipe.h" #include "relocation.h" #include "wheel.h" #include "junitxml.h" +#include "deliverable.h" #define guard_runtime_free(X) do { if (X) { runtime_free(X); X = NULL; } } while (0) #define guard_strlist_free(X) do { if ((*X)) { strlist_free(X); (*X) = NULL; } } while (0) diff --git a/include/os_darwin.h b/include/os_darwin.h index 390968c..465adc4 100644 --- a/include/os_darwin.h +++ b/include/os_darwin.h @@ -2,6 +2,7 @@ #define OMC_OS_DARWIN_H #include +#include #ifndef __DARWIN_64_BIT_INO_T #define statvfs statfs diff --git a/include/os_linux.h b/include/os_linux.h index 8c3aed7..aabf1ff 100644 --- a/include/os_linux.h +++ b/include/os_linux.h @@ -2,6 +2,8 @@ #define OMC_OS_LINUX_H #include +#include +#include #ifndef PATH_MAX #include diff --git a/include/os_windows.h b/include/os_windows.h new file mode 100644 index 0000000..ae7875c --- /dev/null +++ b/include/os_windows.h @@ -0,0 +1,22 @@ +// +// Created by jhunk on 5/19/2024. +// + +#ifndef OMC_OS_WINDOWS_H +#define OMC_OS_WINDOWS_H + + +#include +#include +#include +#define lstat stat +#define NAME_MAX 256 +#define MAXNAMLEN 256 +#define __environ _environ +#undef mkdir +#define mkdir(X, Y) _mkdir(X) + +int setenv(const char *key, const char *value, int overwrite); +char *realpath(const char *path, char **dest); + +#endif //OMC_OS_WINDOWS_H diff --git a/include/relocation.h b/include/relocation.h index 924f00f..6ace8e0 100644 --- a/include/relocation.h +++ b/include/relocation.h @@ -11,7 +11,7 @@ #include #if defined(OMC_OS_DARWIN) #include -# else +#elif defined(OMC_OS_LINUX) #include #endif #include diff --git a/include/str.h b/include/str.h index 8018cc0..60116de 100644 --- a/include/str.h +++ b/include/str.h @@ -333,5 +333,9 @@ char *tolower_s(char *s); * @return pointer to new string */ char *to_short_version(const char *s); +#if defined(OMC_OS_WINDOWS) +char *strsep(char **str, const char *delim); +char *strndup(const char *str, size_t nelem); +#endif #endif //OMC_STR_H diff --git a/include/system.h b/include/system.h index 7428355..9d9eb0f 100644 --- a/include/system.h +++ b/include/system.h @@ -11,7 +11,9 @@ #include #include #include +#if defined(OMC_OS_UNIX) #include +#endif #include struct Process { diff --git a/rules/hst.ini b/rules/hst.ini new file mode 100644 index 0000000..e69de29 diff --git a/src/copy.c b/src/copy.c index dcfd924..de87446 100644 --- a/src/copy.c +++ b/src/copy.c @@ -26,6 +26,7 @@ int copy2(const char *src, const char *dest, unsigned int op) { } stat(dname, &dnamest); +#if ! defined(OMC_OS_WINDOWS) if (S_ISLNK(src_stat.st_mode)) { char lpath[1024] = {0}; if (readlink(src, lpath, sizeof(lpath)) < 0) { @@ -46,7 +47,9 @@ int copy2(const char *src, const char *dest, unsigned int op) { perror(src); return -1; } - } else if (S_ISREG(src_stat.st_mode)) { + } else +#endif + if (S_ISREG(src_stat.st_mode)) { fp1 = fopen(src, "rb"); if (!fp1) { perror(src); @@ -67,13 +70,15 @@ int copy2(const char *src, const char *dest, unsigned int op) { fclose(fp2); if (bytes_written != (size_t) src_stat.st_size) { - fprintf(stderr, "%s: SHORT WRITE (expected %zu bytes, but wrote %zu bytes)\n", dest, src_stat.st_size, bytes_written); + fprintf(stderr, "%s: SHORT WRITE (expected %li bytes, but wrote %zu bytes)\n", dest, src_stat.st_size, bytes_written); return -1; } +#if !defined(OMC_OS_WINDOWS) if (op & CT_OWNER && chown(dest, src_stat.st_uid, src_stat.st_gid) < 0) { perror(dest); } +#endif if (op & CT_PERM && chmod(dest, src_stat.st_mode) < 0) { perror(dest); @@ -173,7 +178,13 @@ int copytree(const char *srcdir, const char *destdir, unsigned int op) { return -1; } - if (d->d_type == DT_DIR) { + int is_dir = 0; +#if defined (OMC_OS_WINDOWS) + is_dir = S_ISDIR(st.st_mode); +#else + is_dir = DT_DIR == rec->d_type; +#endif + if (is_dir) { if (strncmp(src, dest, strlen(src)) == 0) { closedir(dir); return -1; diff --git a/src/deliverable.c b/src/deliverable.c index f72f535..88c42a5 100644 --- a/src/deliverable.c +++ b/src/deliverable.c @@ -1,9 +1,14 @@ #define _GNU_SOURCE -#include #include "omc.h" - -extern struct OMC_GLOBAL globals; +#if !defined(OMC_OS_WINDOWS) +#include +#include +#endif +#include "deliverable.h" +#include "str.h" +#include "strlist.h" +#include "copy.h" static void ini_has_key_required(struct INIFILE *ini, const char *section_name, char *key) { int status = ini_has_key(ini, section_name, key); @@ -98,6 +103,7 @@ int delivery_init_tmpdir(struct Delivery *ctx) { goto l_delivery_init_tmpdir_fatal; } +#if !defined(OMC_OS_WINDOWS) struct statvfs st; if (statvfs(tmpdir, &st) < 0) { goto l_delivery_init_tmpdir_fatal; @@ -114,6 +120,7 @@ int delivery_init_tmpdir(struct Delivery *ctx) { msg(OMC_MSG_ERROR | OMC_MSG_L1, "%s is mounted read-only\n", tmpdir); goto l_delivery_init_tmpdir_fatal; } +#endif if (!globals.tmpdir) { globals.tmpdir = strdup(tmpdir); @@ -140,7 +147,7 @@ void delivery_free(struct Delivery *ctx) { guard_free(ctx->meta.mission); guard_free(ctx->meta.python_compact); guard_free(ctx->meta.based_on); - guard_runtime_free(ctx->runtime.environ); + guard_runtime_free(ctx->runtime.env); guard_free(ctx->storage.root); guard_free(ctx->storage.tmpdir); guard_free(ctx->storage.delivery_dir); @@ -189,7 +196,7 @@ void delivery_free(struct Delivery *ctx) { guard_free(ctx->tests[i].script); guard_free(ctx->tests[i].build_recipe); // test-specific runtime variables - guard_runtime_free(ctx->tests[i].runtime.environ); + guard_runtime_free(ctx->tests[i].runtime.env); } guard_free(ctx->rules.release_fmt); @@ -304,11 +311,6 @@ void delivery_init_dirs_stage1(struct Delivery *ctx) { int delivery_init_platform(struct Delivery *ctx) { msg(OMC_MSG_L2, "Setting architecture\n"); char archsuffix[20]; - struct utsname uts; - if (uname(&uts)) { - msg(OMC_MSG_ERROR | OMC_MSG_L2, "uname() failed: %s\n", strerror(errno)); - return -1; - } ctx->system.platform = calloc(DELIVERY_PLATFORM_MAX + 1, sizeof(*ctx->system.platform)); if (!ctx->system.platform) { @@ -319,6 +321,35 @@ int delivery_init_platform(struct Delivery *ctx) { ctx->system.platform[i] = calloc(DELIVERY_PLATFORM_MAXLEN, sizeof(*ctx->system.platform[0])); } +#if !defined(OMC_OS_WINDOWS) + struct utsname uts; + if (uname(&uts)) { + msg(OMC_MSG_ERROR | OMC_MSG_L2, "uname() failed: %s\n", strerror(errno)); + return -1; + } +#else +#include + struct utsname { + char machine[65]; + char sysname[MAX_COMPUTERNAME_LENGTH + 1]; + } uts; + SYSTEM_INFO si; + GetSystemInfo(&si); + switch (si.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + strcpy(uts.machine, "x86_64"); + break; + case PROCESSOR_ARCHITECTURE_ARM64: + strcpy(uts.machine, "arm64"); + break; + default: + strcpy(uts.machine, "unknown"); + break; + } + unsigned long maxlen = MAX_COMPUTERNAME_LENGTH; + GetComputerNameA(uts.sysname, &maxlen); +#endif + ctx->system.arch = strdup(uts.machine); if (!ctx->system.arch) { // memory error @@ -469,7 +500,7 @@ static int populate_delivery_ini(struct Delivery *ctx) { runtime_set(rt, rtdata->key, rtdata->value); } runtime_apply(rt); - ctx->runtime.environ = rt; + ctx->runtime.env = rt; ini_getval_required(ini, "meta", "mission", INIVAL_TYPE_STR, &val); conv_str(&ctx->meta.mission, val); @@ -604,7 +635,7 @@ static int populate_delivery_ini(struct Delivery *ctx) { conv_str(&ctx->tests[z].build_recipe, val); ini_getval(ini, ini->section[i]->key, "runtime", INIVAL_TO_LIST, &val); - conv_strlist(&ctx->tests[z].runtime.environ, LINE_SEP, val); + conv_strlist(&ctx->tests[z].runtime.env, LINE_SEP, val); z++; } } @@ -963,7 +994,7 @@ void delivery_tests_show(struct Delivery *ctx) { void delivery_runtime_show(struct Delivery *ctx) { printf("\n====RUNTIME====\n"); struct StrList *rt = NULL; - rt = strlist_copy(ctx->runtime.environ); + rt = strlist_copy(ctx->runtime.env); if (!rt) { // no data return; @@ -1063,7 +1094,8 @@ static int filter_repo_tags(char *repo, struct StrList *patterns) { char *tag = strlist_item(tags, i); for (size_t p = 0; p < strlist_count(patterns); p++) { char *pattern = strlist_item(patterns, p); - int match = fnmatch(pattern, tag, 0); + //int match = fnmatch(pattern, tag, 0); + int match = 0; // TODO fnmatch if (!match) { char cmd[PATH_MAX] = {0}; sprintf(cmd, "git tag -d %s", tag); @@ -1159,7 +1191,7 @@ int delivery_install_packages(struct Delivery *ctx, char *conda_install_dir, cha // Activate the requested environment printf("Activating: %s\n", env_name); conda_activate(conda_install_dir, env_name); - runtime_replace(&ctx->runtime.environ, __environ); + runtime_replace(&ctx->runtime.env, __environ); } } @@ -1318,50 +1350,60 @@ int delivery_index_wheel_artifacts(struct Delivery *ctx) { } while ((rec = readdir(dp)) != NULL) { - // skip directories - if (DT_REG == rec->d_type || !strcmp(rec->d_name, "..") || !strcmp(rec->d_name, ".")) { + unsigned is_dir = 0; +#if defined(OMC_OS_WINDOWS) + struct stat st; + if (stat(rec->d_name, &st)) { + perror(rec->d_name); continue; } + is_dir = S_ISDIR(st.st_mode); +#else + is_dir = DT_DIR == rec->d_type; +#endif + // skip directories + if (is_dir || !endswith(rec->d_name, ".whl")) { + + FILE *bottom_fp; + char bottom_index[PATH_MAX * 2]; + memset(bottom_index, 0, sizeof(bottom_index)); + sprintf(bottom_index, "%s/%s/index.html", ctx->storage.wheel_artifact_dir, rec->d_name); + bottom_fp = fopen(bottom_index, "w+"); + if (!bottom_fp) { + return -3; + } - FILE *bottom_fp; - char bottom_index[PATH_MAX * 2]; - memset(bottom_index, 0, sizeof(bottom_index)); - sprintf(bottom_index, "%s/%s/index.html", ctx->storage.wheel_artifact_dir, rec->d_name); - bottom_fp = fopen(bottom_index, "w+"); - if (!bottom_fp) { - return -3; - } - - if (globals.verbose) { - printf("+ %s\n", rec->d_name); - } - // Add record to top level index - fprintf(top_fp, "%s
\n", rec->d_name, rec->d_name); + if (globals.verbose) { + printf("+ %s\n", rec->d_name); + } + // Add record to top level index + fprintf(top_fp, "%s
\n", rec->d_name, rec->d_name); + + char dpath[PATH_MAX * 2]; + memset(dpath, 0, sizeof(dpath)); + sprintf(dpath, "%s/%s", ctx->storage.wheel_artifact_dir, rec->d_name); + struct StrList *packages = listdir(dpath); + if (!packages) { + fclose(top_fp); + fclose(bottom_fp); + return -4; + } - char dpath[PATH_MAX * 2]; - memset(dpath, 0, sizeof(dpath)); - sprintf(dpath, "%s/%s", ctx->storage.wheel_artifact_dir, rec->d_name); - struct StrList *packages = listdir(dpath); - if (!packages) { - fclose(top_fp); + for (size_t i = 0; i < strlist_count(packages); i++) { + char *package = strlist_item(packages, i); + if (!endswith(package, ".whl")) { + continue; + } + if (globals.verbose) { + printf("`- %s\n", package); + } + // Write record to bottom level index + fprintf(bottom_fp, "%s
\n", package, package); + } fclose(bottom_fp); - return -4; - } - for (size_t i = 0; i < strlist_count(packages); i++) { - char *package = strlist_item(packages, i); - if (!endswith(package, ".whl")) { - continue; - } - if (globals.verbose) { - printf("`- %s\n", package); - } - // Write record to bottom level index - fprintf(bottom_fp, "%s
\n", package, package); + guard_strlist_free(&packages); } - fclose(bottom_fp); - - guard_strlist_free(&packages); } closedir(dp); fclose(top_fp); @@ -1409,7 +1451,7 @@ void delivery_conda_enable(struct Delivery *ctx, char *conda_install_dir) { char rcpath[PATH_MAX]; sprintf(rcpath, "%s/%s", conda_install_dir, ".condarc"); setenv("CONDARC", rcpath, 1); - if (runtime_replace(&ctx->runtime.environ, __environ)) { + if (runtime_replace(&ctx->runtime.env, __environ)) { perror("unable to replace runtime environment after activating conda"); exit(1); } diff --git a/src/docker.c b/src/docker.c index f8c9c11..872e06a 100644 --- a/src/docker.c +++ b/src/docker.c @@ -36,7 +36,20 @@ int docker_script(const char *image, char *data, unsigned flags) { return -1; } +#if defined(OMC_OS_WINDOWS) + char tempfile[PATH_MAX]; + strcpy(tempfile, "OMC.docker.XXXXXX"); + if (mkstemp(tempfile)) { + // creating temp file failed + return -1; + } + infile = fopen(tempfile, "w"); + for (size_t i = 0; i < strlen(data); i++) { + fputc(data[i], infile); + } +#else infile = fmemopen(data, strlen(data), "r"); +#endif if (!infile) { // opening memory file for reading failed return -1; @@ -49,6 +62,9 @@ int docker_script(const char *image, char *data, unsigned flags) { } while (!feof(infile)); fclose(infile); +#if defined(OMC_OS_WINDOWS) + remove(tempfile); +#endif return pclose(outfile); } diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e69de29 diff --git a/src/omc_main.c b/src/omc_main.c index 90460ee..e229453 100644 --- a/src/omc_main.c +++ b/src/omc_main.c @@ -331,7 +331,7 @@ int main(int argc, char *argv[]) { exit(1); } - runtime_apply(ctx.runtime.environ); + runtime_apply(ctx.runtime.env); strcpy(env_name, ctx.info.release_name); strcpy(env_name_testing, env_name); strcat(env_name_testing, "-test"); diff --git a/src/str.c b/src/str.c index a5d42a6..45b32df 100644 --- a/src/str.c +++ b/src/str.c @@ -2,7 +2,18 @@ * @file strings.c */ #include -#include "str.h" +#include "omc.h" + +#if defined(OMC_OS_WINDOWS) +char *strsep(char **str, const char *delim) { + static char *last; + return strtok_r(*str, delim, &last); +} + +char *strndup(const char *str, size_t nelem) { + return calloc(nelem, sizeof(*str)); +} +#endif int num_chars(const char *sptr, int ch) { int result = 0; diff --git a/src/system.c b/src/system.c index ca2da97..895ed8a 100644 --- a/src/system.c +++ b/src/system.c @@ -5,6 +5,85 @@ #include "system.h" #include "omc.h" +#if defined(OMC_OS_WINDOWS) +int shell(struct Process *proc, char *args) { + char cmd[OMC_BUFSIZ]; + memset(cmd, 0, sizeof(cmd)); + strcat(cmd, args); + return system(cmd); +} +#else +int shell(struct Process *proc, char *args[]) { + FILE *fp_out, *fp_err; + pid_t pid; + pid_t status; + status = 0; + errno = 0; + + pid = fork(); + if (pid == -1) { + fprintf(stderr, "fork failed\n"); + exit(1); + } else if (pid == 0) { + int retval; + if (proc != NULL) { + if (strlen(proc->standard_output)) { + fp_out = freopen(proc->standard_output, "w+", stdout); + } + + if (strlen(proc->standard_error)) { + fp_err = freopen(proc->standard_error, "w+", stderr); + } + + if (proc->redirect_stderr) { + if (fp_err) { + fclose(fp_err); + fclose(stderr); + } + dup2(fileno(stdout), fileno(stderr)); + } + } + + retval = execv(args[0], args); + fprintf(stderr, "# executing: "); + for (size_t x = 0; args[x] != NULL; x++) { + fprintf(stderr, "%s ", args[x]); + } + + if (proc != NULL && strlen(proc->standard_output)) { + fflush(fp_out); + fclose(fp_out); + fflush(stdout); + fclose(stdout); + } + if (proc != NULL && strlen(proc->standard_error)) { + fflush(fp_err); + fclose(fp_err); + fflush(stderr); + fclose(stderr); + } + exit(retval); + } else { + if (waitpid(pid, &status, WUNTRACED) > 0) { + if (WIFEXITED(status) && WEXITSTATUS(status)) { + if (WEXITSTATUS(status) == 127) { + fprintf(stderr, "execv failed\n"); + } + } else if (WIFSIGNALED(status)) { + fprintf(stderr, "signal received: %d\n", WIFSIGNALED(status)); + } + } else { + fprintf(stderr, "waitpid() failed\n"); + } + } + + + if (proc != NULL) { + proc->returncode = status; + } + return WEXITSTATUS(status); +} + int shell(struct Process *proc, char *args) { FILE *fp_out = NULL; FILE *fp_err = NULL; @@ -96,6 +175,7 @@ int shell(struct Process *proc, char *args) { guard_free(t_name); return WEXITSTATUS(status); } +#endif int shell_safe(struct Process *proc, char *args) { FILE *fp; diff --git a/src/utils.c b/src/utils.c index ea79f10..c62af08 100644 --- a/src/utils.c +++ b/src/utils.c @@ -52,8 +52,16 @@ int rmtree(char *_path) { continue; } + int is_dir = 0; +#if defined(OMC_OS_WINDOWS) + struct stat st; + stat(d_entity->d_name, &st); + is_dir = S_ISDIR(st.st_mode); +#else + is_dir = DT_DIR == rec->d_type; +#endif // Push directories on to the stack first - if (d_entity->d_type == DT_DIR) { + if (is_dir) { rmtree(abspath); } else { remove(abspath); @@ -385,12 +393,21 @@ char *git_rev_parse(const char *path, char *args) { return version; } +#if defined(OMC_OS_WINDOWS) +#define OMC_COLOR_RED "" +#define OMC_COLOR_GREEN "" +#define OMC_COLOR_YELLOW "" +#define OMC_COLOR_BLUE "" +#define OMC_COLOR_WHITE "" +#define OMC_COLOR_RESET "" +#else #define OMC_COLOR_RED "\e[1;91m" #define OMC_COLOR_GREEN "\e[1;92m" #define OMC_COLOR_YELLOW "\e[1;93m" #define OMC_COLOR_BLUE "\e[1;94m" #define OMC_COLOR_WHITE "\e[1;97m" #define OMC_COLOR_RESET "\e[0;37m\e[0m" +#endif void msg(unsigned type, char *fmt, ...) { FILE *stream = NULL; @@ -763,3 +780,51 @@ struct StrList *listdir(const char *path) { return node; } +#if defined(OMC_OS_WINDOWS) +char *realpath(const char *path, char **dest) { + char cwd_start[PATH_MAX] = {0}; + char cwd[PATH_MAX] = {0}; + char where[PATH_MAX] = {0}; + char bname[PATH_MAX] = {0}; + char *w = where; + getcwd(cwd_start, sizeof(cwd) - 1); + strcpy(w, path); + w = path_dirname(w); + if (chdir(w)) { + getcwd(cwd, sizeof(cwd) - 1); + path_basename(bname); + strcat(cwd, bname); + chdir(cwd_start); + } + + char *result; + result = strdup(cwd); + if (!result) { + return NULL; + } + + if (dest) { + *dest = result; + } + + return result; +} + +int setenv(const char *key, const char *value, int overwrite) { + size_t len = 0; + char *data = NULL; + len = strlen(key) + strlen(value) + 2; + data = calloc(len, sizeof(*data)); + if (!data) { + return -1; + } + sprintf(data, "%s=%s", key, value); + if (_putenv(data)) { + free(data); + return 1; + } + + free(data); + return 0; +} +#endif