npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fs-attrs

v1.0.0

Published

Read and change basic Linux file attributes (lsattr/chattr) from Node.js

Readme

fs-attrs

Read and change basic file attributes directly from Node.js — the same attributes lsattr(1) and chattr(1) operate on.

This is a native addon that calls ioctl(2), so there is no shelling out to external binaries at runtime, but a native build toolchain is required to install this module.

If you're looking to work with extended attributes (xattr), see fs-xattr.

Linux only.

Install

npm install fs-attrs

Building from source needs a C++ toolchain and linux/fs.h (the linux-libc-dev / kernel-headers package).

Usage

const { lsattr, chattr } = require('fs-attrs');

await lsattr('/home/me/test');        // => [ 'i' ]

await chattr('/var/log/audit.log', '+a');   // append-only
await chattr('/tmp/scratch', '-A');         // stop suppressing atime updates
await chattr('/srv/data', '=dA');           // exactly 'd' and 'A', nothing else

Both functions also accept an open file descriptor in place of a path:

const handle = await fs.promises.open('/srv/data/file', 'r');
try {
  await chattr(handle.fd, '+C');
  console.log(await lsattr(handle.fd));
} finally {
  await handle.close();
}

API

lsattr(path: string): Promise<string[]>

lsattr(fd: number): Promise<string[]>

Resolves with the letters of the attributes that are set, in lsattr(1) order. Only the attributes in the tables below are reported; other bits the kernel may set (FS_EXTENT_FL, FS_DAX_FL, …) are ignored.

chattr(path: string, attributes: string): Promise<void>

chattr(fd: number, attributes: string): Promise<void>

Reads the current flags, applies attributes, and writes the result back.

attributes uses chattr(1) syntax:

| Spec | Effect | | -------- | ---------------------------------------------------------- | | +i | add i | | -i | remove i | | =i | set exactly i, clearing every other writable attribute | | = | clear every writable attribute | | +ci | add both c and i | | +i-A | add i and remove A in one call | | +i, -A | commas and spaces are ignored separators |

When the same letter appears in more than one clause, the last one wins: '+A-A' leaves A unset.

Naming a read-only attribute (E, I, N, V) rejects with a TypeError.

Attributes

These can be read and written:

| Letter | Flag | Meaning | | ------ | -------------------- | ----------------------------- | | a | FS_APPEND_FL | append only | | A | FS_NOATIME_FL | do not update atime | | c | FS_COMPR_FL | compressed | | C | FS_NOCOW_FL | no copy-on-write | | d | FS_NODUMP_FL | no dump | | D | FS_DIRSYNC_FL | synchronous directory updates | | i | FS_IMMUTABLE_FL | immutable | | j | FS_JOURNAL_DATA_FL | data journalling | | P | FS_PROJINHERIT_FL | project hierarchy | | s | FS_SECRM_FL | secure deletion | | S | FS_SYNC_FL | synchronous updates | | t | FS_NOTAIL_FL | no tail-merging | | T | FS_TOPDIR_FL | top of directory hierarchy | | u | FS_UNRM_FL | undeletable |

Which of these actually work depends on the filesystem and on your privileges. ext4 has no C; btrfs has no j and rejects c together with C; setting i or a requires CAP_LINUX_IMMUTABLE. Unsupported combinations surface as ENOTSUP, EINVAL, or EPERM from the kernel.

These are read-only — lsattr reports them, chattr refuses them:

| Letter | Flag | Meaning | | ------ | ------------------- | ------------------------------- | | E | FS_ENCRYPT_FL | encrypted | | I | FS_INDEX_FL | hash-indexed directory | | N | FS_INLINE_DATA_FL | data stored inline in the inode | | V | FS_VERITY_FL | fs-verity protected |

The filesystem sets these as a side effect of other operations — enabling encryption or fs-verity on a file, storing a small file's data inline, or building a hashed directory index — and FS_IOC_SETFLAGS does not accept them. Turning them on is a job for FS_IOC_SET_ENCRYPTION_POLICY, FS_IOC_ENABLE_VERITY, or the filesystem itself, and none of them can be turned back off.

await lsattr('/srv/protected.bin');       // => [ 'V' ]
await chattr('/srv/protected.bin', '-V'); // TypeError: attribute 'V' is read-only…

Errors

Failures from open(2) and ioctl(2) reject with an Error shaped like a Node.js system error:

try {
  await chattr('/etc/passwd', '+i');
} catch (err) {
  err.code;     // 'EPERM'
  err.errno;    // -1
  err.syscall;  // 'ioctl'
  err.path;     // '/etc/passwd'   (or err.fd for the fd overloads)
  err.message;  // "EPERM: operation not permitted, ioctl '/etc/passwd'"
}

Invalid arguments — a bad target type, an empty path, an unparsable attribute string — reject with a TypeError, and the file is never touched.

Notes

  • Paths follow symlinks, matching chattr(1) on a non-recursive invocation.
  • A file descriptor you pass in is never closed, but it must stay open until the returned promise settles. A path is opened O_RDONLY | O_NONBLOCK | O_CLOEXEC and closed again.
  • = preserves everything it cannot write. It clears only the writable attributes, so the read-only ones above and kernel-internal flags such as FS_EXTENT_FL survive. chattr(1) writes the whole flags word instead.
  • The write is unconditional, matching chattr(1): adding an attribute that is already set still issues FS_IOC_SETFLAGS, and can still fail with EPERM.

Development

npm install     # builds the addon
npm run rebuild # rebuild after editing src/
npm test

License

MIT