NAME
Archive::Asar - list/extract/create Electron ASAR (Atom Shell Archive) files
SYNOPSIS
use Archive::Asar;
my $asar = Archive::Asar->new_from_file('app.asar'); # or
my $asar = Archive::Asar->new_from_string($blob); # or
my $asar = Archive::Asar->new_from_fh(\*STDIN, '(stdin)'); # or
my $asar = Archive::Asar->new_empty;
my $index_structure = $asar->index_raw;
my $info = $asar->get_entry('file/foo.txt');
$asar->extract_to($target_directory);
$asar->remove($path);
$asar->add_directory($path);
$asar->add_link($path, $target);
$asar->add_file($path, $contents, $executable);
$asar->ingest($path, $file);
$asar->write_to_fh($fh);
$asar->write_to_file('output.asar');
DESCRIPTION
Archive::Asar provides an object-oriented interface for handling Electron .asar files ("Atom Shell Archive").
In the following description, a $path parameter refers to a member of the archive. It is either a reference to an array of path components (e.g. ['foo', 'bar', 'hello.txt']) or a string with path components separated by / (e.g. 'foo/bar/hello.txt') or (for Windows compatibility) by \ (e.g. 'foo\\bar\\hello.txt').
Use an empty path ([] or '') to refer to the root level of the archive, which is always a directory.
Constructors
- new_from_fh
-
Usage:
my $asar = Archive::Asar->new_from_fh($handle, $name);Usage:
my $asar = Archive::Asar->new_from_fh($handle);$handleis the filehandle to read from (must be seekable, i.e. not a pipe, terminal, socket, etc).$nameis the name of the archive (used in error messages); it defaults to'(fh)'.$handleneed not be a built-in Perl filehandle; it can be any object that responds to the required methodsseek,tell, andread. If it is a filehandle, it needs to read binary data verbatim (without decoding), i.e. you should open it in<:rawmode or callbinmodeon it (see "binmode FILEHANDLE" in perlfunc.Returns the initialized object or throws an exception on error.
- new_from_file
-
Usage:
my $asar = Archive::Asar->new_from_file($file);Like "new_from_fh", but opens
$filefirst (and automatically uses$fileas the name of the archive in error messages). - new_from_string
-
Usage:
my $asar = Archive::Asar->new_from_string($blob, $name);Usage:
my $asar = Archive::Asar->new_from_string($blob);Like "new_from_fh", but reads the archive data directly from a byte string, not a filehandle.
$namedefaults to'(buffer)'. - new_empty
-
Usage:
my $asar = Archive::Asar->new_empty($name);Usage:
my $asar = Archive::Asar->new_empty();Creates an empty in-memory archive.
$nameis the name of the archive (used in error messages); it defaults to'(new)'.
Methods
- index_raw
-
Usage:
my $index = $asar->index_raw;Returns the parsed index data structure stored as JSON in the ASAR file.
The returned data structure must not be modified.
- get_entry
-
Usage:
my $entry = $asar->get_entry($path);Returns information about the archive member stored at
$path.If the specified path doesn't exist or anything else goes wrong, an exception is thrown.
The return value is a hash reference with a
typefield. There are three possible types:- directory
-
{ type => 'directory', entries => [...], unpacked? => true }An entry of type
directoryhas anentriesfield (an arrayref of strings) listing the entries in that directory. It may also have anunpackedfield (normally set totrueif present). - link
-
{ type => 'link', target => '...', unpacked? => true }An entry of type
linkhas atargetfield (a string) specifying the target of the symbolic link.Beware: The
targetfield is not validated! It may be any string provided by the archive. It may refer to a file outside of the archive or it may not be a valid filename at all. - file
-
{ type => 'file', unpacked => true }{ type => 'file', contents => '...', executable? => true, integrity? => {...} }An entry of type
filehas either a trueunpackedfield, indicating that the file is stored externally (outside of the packed archive), or acontentsfield giving the contents of the file as a string.In the latter case, it may also have an
executablefield, which (if true) indicates that the file is executable, and/or anintegrityfield, which contains checksum information in the following format:{ algorithm => 'SHA256', hash => '...', # lowercase hex blockSize => ..., blocks => [...], }algorithmis the hashing algorithm to use (currently alwaysSHA256; see Digest::SHA).hashis the result of hashing the file contents (in lowercase hex format, two hex digits per byte).blockSizeis an integer. Theblocksfield is an array of the results of splitting the file contents into chunks of (at most)blockSizebytes and hashing each chunk separately, in the same format ashash.For example, an empty file may appear as:
{ type => 'file', contents => '', integrity => { algorithm => 'SHA256', hash => 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', blockSize => 0x400000, blocks => ['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'], }, }
- extract_to
-
Usage:
$asar->extract_to($target_directory, $options = {});Extracts the contents of the archive into the given
$target_directory, which is automatically created if it doesn't exist yet.The
$optionsargument is optional, but must be a hash reference if given. Currently only one option is supported:- unpacked_dir
-
If
unpacked_diris set to a defined value, files markedunpackedin the archive will be read from this directory (and copied to$target_directory).Otherwise
unpackedfiles will be skipped when extracting.
- remove
-
Usage:
my $removed = $asar->remove($path);Removes the specified path from the archive. If the path refers to a directory, everything in it is removed as well (like
rm -r).The last component of the specified path need not exist. If it doesn't exist,
removedoes nothing and returns false; otherwise it returns true. - add_directory
-
Usage:
$asar->add_directory($path);Creates a directory at the specified path.
Does nothing if the specified path already exists. Non-existent intermediate directories in
$pathare created automatically.my $asar= Archive::Asar->new_empty; $asar->add_directory('foo/bar/baz'); # Automatically does # $asar->add_directory('foo'); # $asar->add_directory('foo/bar'); # $asar->add_directory('foo/bar/baz'); - add_link
-
Usage:
$asar->add_link($path, $target);Creates a symbolic link at the specified path pointing to
$target, which must be a string.Throws an error if the specified path already exists. Non-existent intermediate directories in
$pathare created automatically. - add_file
-
Usage:
$asar->add_file($path, $contents, $executable);Usage:
$asar->add_file($path, $contents);Creates a file at the specified path containing
$contents, which must be a byte string. If$executableis passed as a true value, the archived file is marked as executable.Throws an error if the specified path already exists. Non-existent intermediate directories in
$pathare created automatically. - ingest
-
Usage:
$asar->ingest($path, $file);Copies a file (or directory hierarchy, recursively) from
$fileinto the archive under$path. - write_to_fh
-
Usage:
$asar->write_to_fh($handle, $name);Usage:
$asar->write_to_fh($handle);Writes ASAR data to the specified
$handle.$nameis the name of the archive (used in error messages); it defaults to'(fh)'.$handleneed not be a built-in Perl filehandle; it can be any object that responds to the required methodsprintandflush. If it is a filehandle, it needs to write binary data verbatim (without encoding), i.e. you should open it in>:rawmode or callbinmodeon it (see "binmode FILEHANDLE" in perlfunc. - write_to_file
-
Usage:
$asar->write_to_file($file);Like "write_to_fh", but opens
$filefirst (and automatically uses$fileas the name of the archive in error messages).This method actually writes to a temporary file next to
$fileand renames it to$fileat the end. This means if$filealready exists, it will be overwritten and along with it any special modes/permissions it may have.
BUGS AND LIMITATIONS
Creating and modifying archives is not supported.
Support for "unpacked" archive members is rudimentary.
Tests are incomplete.
AUTHOR
Lukas Mai, <lmai at web.de>
COPYRIGHT & LICENSE
Copyright 2026 Lukas Mai.
This module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.