-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
158 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,72 @@ | ||
const typeFlag = { | ||
reg_type: '0', | ||
areg_type: '\0', | ||
link_type: '1', | ||
sym_type: '2', | ||
chr_type: '3', | ||
blk_type: '4', | ||
dir_type: '5', | ||
fifo_type: '6', | ||
cont_type: '7' | ||
} as const | ||
// const typeFlag = { | ||
// reg_type: '0', | ||
// areg_type: '\0', | ||
// link_type: '1', | ||
// sym_type: '2', | ||
// chr_type: '3', | ||
// blk_type: '4', | ||
// dir_type: '5', | ||
// fifo_type: '6', | ||
// cont_type: '7' | ||
// } as const | ||
|
||
const mod = { | ||
ts_uid: 0o4000, | ||
ts_gid: 0o2000, | ||
ts_vtx: 0o1000, | ||
tu_read: 0o0400, | ||
tu_write: 0o0200, | ||
tu_exec: 0o0100, | ||
tg_read: 0o0040, | ||
tg_write: 0o0020, | ||
tg_exec: 0o0010, | ||
to_read: 0o0004, | ||
to_write: 0o0002, | ||
to_exec: 0o0001 | ||
} | ||
// const mod = { | ||
// ts_uid: 0o4000, | ||
// ts_gid: 0o2000, | ||
// ts_vtx: 0o1000, | ||
// tu_read: 0o0400, | ||
// tu_write: 0o0200, | ||
// tu_exec: 0o0100, | ||
// tg_read: 0o0040, | ||
// tg_write: 0o0020, | ||
// tg_exec: 0o0010, | ||
// to_read: 0o0004, | ||
// to_write: 0o0002, | ||
// to_exec: 0o0001 | ||
// } | ||
|
||
export type TypeFlag = typeof typeFlag[keyof typeof typeFlag] | ||
// export type TypeFlag = typeof typeFlag[keyof typeof typeFlag] | ||
|
||
export type Mod = typeof mod[keyof typeof mod] | ||
// export type Mod = typeof mod[keyof typeof mod] | ||
|
||
// export const f_mod = mod. | ||
// // export const f_mod = mod. | ||
|
||
export declare const f_mod: number | ||
// export declare const f_mod: number | ||
|
||
export declare const d_mod: number | ||
// export declare const d_mod: number | ||
|
||
export interface HeadOptions { | ||
name: string | ||
mode: number | ||
uid: number | ||
gid: number | ||
size: number | ||
typeflag: TypeFlag | ||
linkname: string | ||
magic: string | ||
version: string | ||
uname: string | ||
gname: string | ||
devmajor: number | ||
devminor: number | ||
mtime: number | ||
prefix: string | ||
} | ||
// export interface HeadOptions { | ||
// name: string | ||
// mode: number | ||
// uid: number | ||
// gid: number | ||
// size: number | ||
// typeflag: TypeFlag | ||
// linkname: string | ||
// magic: string | ||
// version: string | ||
// uname: string | ||
// gname: string | ||
// devmajor: number | ||
// devminor: number | ||
// mtime: number | ||
// prefix: string | ||
// } | ||
|
||
export interface DecodeOptions { | ||
filenameEncoding: string | ||
allowunknowFormat: boolean | ||
} | ||
// export interface DecodeOptions { | ||
// filenameEncoding: string | ||
// allowunknowFormat: boolean | ||
// } | ||
|
||
export declare function encode(options: HeadOptions): Uint8Array | ||
// export declare function encode(options: HeadOptions): Uint8Array | ||
|
||
export declare function decode(b: Uint8Array, options: DecodeOptions): Partial<HeadOptions> | ||
// export declare function decode(b: Uint8Array, options: DecodeOptions): Partial<HeadOptions> | ||
|
||
export interface PackInstance { | ||
add: (binary: Uint8Array, options: HeadOptions) => void | ||
done: () => void | ||
} | ||
// export interface PackInstance { | ||
// add: (binary: Uint8Array, options: HeadOptions) => void | ||
// done: () => void | ||
// } | ||
|
||
export declare function pack(): PackInstance | ||
// export declare function pack(): PackInstance | ||
|
||
export * from './head' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Readable, Writable } from 'stream' | ||
import type { ReadableOptions, WritableOptions } from 'stream' | ||
import { F_MODE, TypeFlag, encode } from './head' | ||
import type { EncodingHeadOptions } from './head' | ||
|
||
export type PackOptions = Partial<Omit<EncodingHeadOptions, 'name' | 'size' | 'mtime'>> & { | ||
filename: string | ||
} | ||
|
||
function createReadbleStream(options?: ReadableOptions) { | ||
return new Readable(options) | ||
} | ||
|
||
function createWriteableStream(options?: WritableOptions) { | ||
return new Writable(options) | ||
} | ||
|
||
// New archives should be created using REGTYPE. | ||
const defaultPackOptions = { | ||
mode: F_MODE, | ||
uid: 0, | ||
gid: 0, | ||
typeflag: TypeFlag.REG_TYPE, | ||
devmajor: 0, | ||
devminor: 0 | ||
} satisfies Partial<EncodingHeadOptions> | ||
|
||
export class Pack { | ||
private reader: Readable | ||
private finished: boolean | ||
constructor() { | ||
this.reader = createReadbleStream() | ||
this.finished = false | ||
} | ||
|
||
private resolveHeadOptions(size: number, options: PackOptions): EncodingHeadOptions { | ||
const { filename, ...rest } = options | ||
|
||
return { ...defaultPackOptions, ...rest, name: filename, mtime: Math.floor(Date.now() / 1000), size } | ||
} | ||
|
||
add(binary: Uint8Array, options: PackOptions) { | ||
const resolved = this.resolveHeadOptions(binary.length, options) | ||
this.transport(binary, resolved) | ||
} | ||
|
||
done() { | ||
if (this.finished) return | ||
this.finished = true | ||
// The end of tar is two 512 byte blocks of zeros | ||
// For performance reasone, we should call push as less as possible | ||
this.reader.push(new Uint8Array(1024)) | ||
this.reader.push(null) | ||
} | ||
|
||
private transport(binary: Uint8Array, resolvedOptions: EncodingHeadOptions) { | ||
const writer = createWriteableStream({ | ||
write: (chunk, encoding, callback) => { | ||
this.reader.push(encode(resolvedOptions)) | ||
this.reader.push(chunk) | ||
callback() | ||
}, | ||
final: (callback) => { | ||
this.reader.push(null) | ||
callback() | ||
} | ||
}) | ||
writer.write(binary) | ||
} | ||
|
||
receiver() { | ||
return this.reader | ||
} | ||
} | ||
|
||
export function createPack() { | ||
return new Pack() | ||
} | ||
|
||
export class Extract {} | ||
|
||
export function createExtract() { | ||
return new Extract() | ||
} | ||
|
||
const pack = createPack() | ||
|
||
pack.add(new Uint8Array(), { filename: 'test.txt' }) |