import assert from 'node:assert/strict' import {constants} from 'node:fs' import {open,lstat,realpath,link,unlink} from 'node:fs/promises' import path from 'node:path' import {createHash} from 'node:crypto' export const sha=bytes=>createHash('sha256').update(bytes).digest('hex') export async function protectedDirectory(directory){ assert(process.platform!=='win32'&&typeof process.getuid==='function','Native Windows ACL backend unavailable') assert(path.isAbsolute(directory)&&await realpath(directory)===directory) const uid=process.getuid(),s=await lstat(directory) assert(s.isDirectory()&&!s.isSymbolicLink()&&s.uid===uid&&(s.mode&0o077)===0) for(let p=path.dirname(directory);;p=path.dirname(p)){const s=await lstat(p);assert(s.isDirectory()&&!s.isSymbolicLink()&&(s.uid===uid||s.uid===0));assert((s.mode&0o022)===0||s.uid===0&&(s.mode&0o1000)!==0);if(p===path.dirname(p))break} } export async function readProtected(file,maximum,expectedSha){ await protectedDirectory(path.dirname(file));assert(await realpath(file)===file) const f=await open(file,constants.O_RDONLY|constants.O_NOFOLLOW) try{ const a=await f.stat();assert(a.isFile()&&a.uid===process.getuid()&&(a.mode&0o077)===0&&a.size>0&&a.size<=maximum) const out=Buffer.alloc(a.size+1);let size=0 while(size{const d=await open(directory,constants.O_RDONLY|constants.O_DIRECTORY|constants.O_NOFOLLOW);try{await d.sync()}finally{await d.close()}} try{ identity=await handle.stat({bigint:true});await handle.writeFile('mmapp-writer-journal-lease-v1\n');await handle.sync();await syncDirectory() result=await work() }catch(error){primary=error;failed=true} finally{ try{ await protectedDirectory(directory) const current=await lstat(filename,{bigint:true}) if(!identity||!current.isFile()||current.isSymbolicLink()||current.dev!==identity.dev||current.ino!==identity.ino)throw Error('Journal lease identity changed') await unlink(filename);await syncDirectory() }catch(error){cleanupFailed=true;primary??=error} try{await handle.close()}catch(error){cleanupFailed=true;primary??=error} } // Known COMMIT remains known if the filesystem cleanup fails later. if(!failed&&result?.outcome==='committed'&&cleanupFailed)return Object.freeze({...result,journalUnconfirmed:true}) if(failed||cleanupFailed)throw primary return result }