MVMint64 MVM_file_isexecutable(MVMThreadContext *tc, MVMString *filename, MVMint32 use_lstat) { if (!MVM_file_exists(tc, filename, use_lstat)) return 0; else { MVMint64 r = 0; uv_stat_t statbuf = file_info(tc, filename, use_lstat); if ((statbuf.st_mode & S_IFMT) == S_IFDIR) return 1; else { // true if fileext is in PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC MVMString *dot = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "."); MVMROOT(tc, dot, { MVMint64 n = MVM_string_index_from_end(tc, filename, dot, 0); if (n >= 0) { MVMString *fileext = MVM_string_substring(tc, filename, n, -1); char *ext = MVM_string_utf8_encode_C_string(tc, fileext); char *pext = getenv("PATHEXT"); int plen = strlen(pext); int i; for (i = 0; i < plen; i++) { if (0 == stricmp(ext, pext++)) { r = 1; break; } } MVM_free(ext); MVM_free(pext); } }); } return r; }
MVMint64 MVM_file_stat(MVMThreadContext *tc, MVMString *fn, MVMint64 status) { MVMint64 r = -1; switch (status) { case MVM_stat_exists: r = MVM_file_exists(tc, fn); break; case MVM_stat_filesize: r = MVM_file_info(tc, fn, APR_FINFO_SIZE).size; break; case MVM_stat_isdir: r = MVM_file_info(tc, fn, APR_FINFO_TYPE).filetype & APR_DIR ? 1 : 0; break; case MVM_stat_isreg: r = MVM_file_info(tc, fn, APR_FINFO_TYPE).filetype & APR_REG ? 1 : 0; break; case MVM_stat_isdev: r = MVM_file_info(tc, fn, APR_FINFO_TYPE).filetype & (APR_CHR|APR_BLK) ? 1 : 0; break; case MVM_stat_createtime: r = MVM_file_info(tc, fn, APR_FINFO_CTIME).ctime; break; case MVM_stat_accesstime: r = MVM_file_info(tc, fn, APR_FINFO_ATIME).atime; break; case MVM_stat_modifytime: r = MVM_file_info(tc, fn, APR_FINFO_MTIME).mtime; break; case MVM_stat_changetime: r = MVM_file_info(tc, fn, APR_FINFO_CTIME).ctime; break; case MVM_stat_backuptime: r = -1; break; case MVM_stat_uid: r = MVM_file_info(tc, fn, APR_FINFO_USER).user; break; case MVM_stat_gid: r = MVM_file_info(tc, fn, APR_FINFO_GROUP).group; break; case MVM_stat_islnk: r = MVM_file_info(tc, fn, APR_FINFO_TYPE).filetype & APR_LNK ? 1 : 0; break; case MVM_stat_platform_dev: r = MVM_file_info(tc, fn, APR_FINFO_DEV).device; break; case MVM_stat_platform_inode: r = MVM_file_info(tc, fn, APR_FINFO_INODE).inode; break; case MVM_stat_platform_mode: r = MVM_file_info(tc, fn, APR_FINFO_PROT).protection; break; case MVM_stat_platform_nlinks: r = MVM_file_info(tc, fn, APR_FINFO_NLINK).nlink; break; case MVM_stat_platform_devtype: r = -1; break; case MVM_stat_platform_blocksize: r = MVM_file_info(tc, fn, APR_FINFO_CSIZE).csize; break; case MVM_stat_platform_blocks: r = -1; break; default: break; } return r; }
MVMint64 MVM_file_stat(MVMThreadContext *tc, MVMString *filename, MVMint64 status, MVMint32 use_lstat) { MVMint64 r = -1; switch (status) { case MVM_STAT_EXISTS: r = MVM_file_exists(tc, filename, use_lstat); break; case MVM_STAT_FILESIZE: { char * const a = MVM_string_utf8_encode_C_string(tc, filename); uv_fs_t req; if ((use_lstat ? uv_fs_lstat(tc->loop, &req, a, NULL) : uv_fs_stat(tc->loop, &req, a, NULL) ) < 0) { MVM_free(a); MVM_exception_throw_adhoc(tc, "Failed to stat file: %s", uv_strerror(req.result)); } MVM_free(a); r = req.statbuf.st_size; break; } case MVM_STAT_ISDIR: r = (file_info(tc, filename, use_lstat).st_mode & S_IFMT) == S_IFDIR; break; case MVM_STAT_ISREG: r = (file_info(tc, filename, use_lstat).st_mode & S_IFMT) == S_IFREG; break; case MVM_STAT_ISDEV: { const int mode = file_info(tc, filename, use_lstat).st_mode; #ifdef _WIN32 r = mode & S_IFMT == S_IFCHR; #else r = (mode & S_IFMT) == S_IFCHR || (mode & S_IFMT) == S_IFBLK; #endif break; } case MVM_STAT_CREATETIME: r = file_info(tc, filename, use_lstat).st_ctim.tv_sec; break; case MVM_STAT_ACCESSTIME: r = file_info(tc, filename, use_lstat).st_atim.tv_sec; break; case MVM_STAT_MODIFYTIME: r = file_info(tc, filename, use_lstat).st_mtim.tv_sec; break; case MVM_STAT_CHANGETIME: r = file_info(tc, filename, use_lstat).st_ctim.tv_sec; break; /* case MVM_STAT_BACKUPTIME: r = -1; break; */ case MVM_STAT_UID: r = file_info(tc, filename, use_lstat).st_uid; break; case MVM_STAT_GID: r = file_info(tc, filename, use_lstat).st_gid; break; case MVM_STAT_ISLNK: r = (file_info(tc, filename, 1).st_mode & S_IFMT) == S_IFLNK; break; case MVM_STAT_PLATFORM_DEV: r = file_info(tc, filename, use_lstat).st_dev; break; case MVM_STAT_PLATFORM_INODE: r = file_info(tc, filename, use_lstat).st_ino; break; case MVM_STAT_PLATFORM_MODE: r = file_info(tc, filename, use_lstat).st_mode; break; case MVM_STAT_PLATFORM_NLINKS: r = file_info(tc, filename, use_lstat).st_nlink; break; case MVM_STAT_PLATFORM_DEVTYPE: r = file_info(tc, filename, use_lstat).st_rdev; break; case MVM_STAT_PLATFORM_BLOCKSIZE: r = file_info(tc, filename, use_lstat).st_blksize; break; case MVM_STAT_PLATFORM_BLOCKS: r = file_info(tc, filename, use_lstat).st_blocks; break; default: break; } return r; }