Skip to content

Instantly share code, notes, and snippets.

@T99
Last active July 18, 2022 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save T99/eea59467049b0ec6051f1a0e530f5e75 to your computer and use it in GitHub Desktop.
Save T99/eea59467049b0ec6051f1a0e530f5e75 to your computer and use it in GitHub Desktop.
A more accessible API wrapper over Node's builtin `fs.stat`.
/*
* Created by Trevor Sears <trevor@trevorsears.com> (https://trevorsears.com/).
* 2:49 PM -- July 18th, 2022
*/
import fs from "fs";
import process from "node:process";
export type CheckFileOptions = {
isFile?: boolean,
isDirectory?: boolean,
isReadable?: boolean,
isWriteable?: boolean,
isExecutable?: boolean,
};
export async function checkFile(filePath: string,
options?: CheckFileOptions): Promise<boolean> {
let stats: fs.Stats;
try {
stats = await fs.promises.stat(filePath);
} catch (error: any) {
if (error?.code === "ENOENT") return false;
else throw error;
}
if (options?.isFile === true && !stats.isFile()) return false;
if (options?.isDirectory === true && !stats.isDirectory()) return false;
if (options?.isReadable === true) {
const readableByAll: boolean =
(stats.mode & fs.constants.S_IROTH) === fs.constants.S_IROTH;
const readableByGroup: boolean = (
((stats.mode & fs.constants.S_IRGRP) === fs.constants.S_IRGRP) &&
(process.getegid !== undefined) &&
(stats.gid === process.getegid())
);
const readableByUser: boolean = (
((stats.mode & fs.constants.S_IRUSR) === fs.constants.S_IRUSR) &&
(process.geteuid !== undefined) &&
(stats.uid === process.geteuid())
);
if (!readableByAll && !readableByGroup && !readableByUser) {
return false;
}
}
if (options?.isWriteable === true) {
const writeableByAll: boolean =
(stats.mode & fs.constants.S_IWOTH) === fs.constants.S_IWOTH;
const writeableByGroup: boolean = (
((stats.mode & fs.constants.S_IWGRP) === fs.constants.S_IWGRP) &&
(process.getegid !== undefined) &&
(stats.gid === process.getegid())
);
const writeableByUser: boolean = (
((stats.mode & fs.constants.S_IWUSR) === fs.constants.S_IWUSR) &&
(process.geteuid !== undefined) &&
(stats.uid === process.geteuid())
);
if (!writeableByAll && !writeableByGroup && !writeableByUser) {
return false;
}
}
if (options?.isExecutable === true) {
const executableByAll: boolean =
(stats.mode & fs.constants.S_IXOTH) === fs.constants.S_IXOTH;
const executableByGroup: boolean = (
((stats.mode & fs.constants.S_IXGRP) === fs.constants.S_IXGRP) &&
(process.getegid !== undefined) &&
(stats.gid === process.getegid())
);
const executableByUser: boolean = (
((stats.mode & fs.constants.S_IXUSR) === fs.constants.S_IXUSR) &&
(process.geteuid !== undefined) &&
(stats.uid === process.geteuid())
);
if (!executableByAll && !executableByGroup && !executableByUser) {
return false;
}
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment