@ccos/package_maker
Version:
Coocaa WebOS APP Command-Line Tools.
221 lines (212 loc) • 8.13 kB
JavaScript
import path from 'path';
import fs from 'fs';
let currTimeStamp = 0;
function numberToOctalString(number, maxlength) {
let octStr = number.toString(8);
if (octStr.length < maxlength) {
let fillSize = maxlength - octStr.length;
let prefix = '';
for (let i = 0; i < fillSize; i++) {
prefix = prefix + '0';
}
octStr = prefix + octStr;
}
return octStr;
}
function writeTarHeader(tarFileHandler, shortPath, isDir, fileSize) {
let nameBuf = Buffer.from(shortPath, 'utf8');
const header = Buffer.alloc(512);
header.fill(0);
if (nameBuf.length > 99) { // long name
//console.log('longname: ' + shortPath);
//
let longNameLength = nameBuf.length + 1;
//=====fill header==========
// name
const longLinkFlagBuf = Buffer.from('././@LongLink', 'utf8');
header.fill(longLinkFlagBuf, 0, longLinkFlagBuf.length);
// file mode
const file_mode = Buffer.from('0000644', 'utf8');
header.fill(file_mode, 0x0064, 0x0064 + file_mode.length);
// owner user ID
const uid = Buffer.from('0000000', 'utf8');
header.fill(uid, 0x006C, 0x006C + uid.length);
// owner group ID
const gid = Buffer.from('0000000', 'utf8');
header.fill(gid, 0x0074, 0x0074 + gid.length);
// length of file in bytes
const filesize = Buffer.from(numberToOctalString(longNameLength, 11), 'utf8');
header.fill(filesize, 0x007C, 0x007C + filesize.length);
// modify time of file
const modifytime = Buffer.from(numberToOctalString(0, 11), 'utf8');
header.fill(modifytime, 0x0088, 0x0088 + modifytime.length);
// type of file
const filetype = Buffer.from('L', 'utf8');
header.fill(filetype, 0x009C, 0x009C + filetype.length);
// USTAR
const ustar = Buffer.from('ustar ', 'utf8');
header.fill(ustar, 0x0101, 0x0101 + ustar.length);
// checksum
const dummy_checksum = Buffer.from(' ', 'utf8');
header.fill(dummy_checksum, 0x0094, 0x0094 + dummy_checksum.length);
let curSum = 0;
for (let i = 0; i < 512; i++) {
curSum += header.readUInt8(i);
}
const checksum = Buffer.from(numberToOctalString(curSum, 7), 'utf8');
header.fill(checksum, 0x0094, 0x0094 + checksum.length);
//
fs.writeSync(tarFileHandler, header, 0, 512, null);
//
//写入文件名
//
const a1 = parseInt(longNameLength / 512);
const a2 = longNameLength % 512;
let blockCount = a1;
if (a2 != 0) {
blockCount ++;
}
let longNameBuffer = Buffer.alloc(512 * blockCount);
longNameBuffer.fill(0);
longNameBuffer.fill(nameBuf, 0, nameBuf.length);
fs.writeSync(tarFileHandler, longNameBuffer, 0, 512 * blockCount, null);
//
let newShortName = '@PathCut/_pc_root/' + shortPath;
newShortName = newShortName.substring(0, 100);
nameBuf = Buffer.from(newShortName, 'utf8');
}
//=====fill header==========
// name
header.fill(nameBuf, 0, nameBuf.length);
// file mode
const file_mode = Buffer.from('0000777', 'utf8');
header.fill(file_mode, 0x0064, 0x0064 + file_mode.length);
// owner user ID
const uid = Buffer.from('0000000', 'utf8');
header.fill(uid, 0x006C, 0x006C + uid.length);
// owner group ID
const gid = Buffer.from('0000000', 'utf8');
header.fill(gid, 0x0074, 0x0074 + gid.length);
// length of file in bytes
const filesize = Buffer.from(numberToOctalString(fileSize, 11), 'utf8');
header.fill(filesize, 0x007C, 0x007C + filesize.length);
// modify time of file
const modifytime = Buffer.from(numberToOctalString(currTimeStamp, 11), 'utf8');
header.fill(modifytime, 0x0088, 0x0088 + modifytime.length);
// type of file
const filetype = Buffer.from(isDir ? '5' : '0', 'utf8');
header.fill(filetype, 0x009C, 0x009C + filetype.length);
// USTAR
const ustar = Buffer.from('ustar ', 'utf8');
header.fill(ustar, 0x0101, 0x0101 + ustar.length);
// checksum
const dummy_checksum = Buffer.from(' ', 'utf8');
header.fill(dummy_checksum, 0x0094, 0x0094 + dummy_checksum.length);
let curSum = 0;
for (let i = 0; i < 512; i++) {
curSum += header.readUInt8(i);
}
const checksum = Buffer.from(numberToOctalString(curSum, 7), 'utf8');
header.fill(checksum, 0x0094, 0x0094 + checksum.length);
//
fs.writeSync(tarFileHandler, header, 0, 512, null);
}
function addItem(tarFileHandler, fromInfo, fileSize) {
if (fromInfo.isDir) {
//
// 插入tar内容
if (fromInfo.shortPath != '') {
writeTarHeader(tarFileHandler, fromInfo.shortPath, true, 0);
}
//console.log('tar增加目录:' + fromInfo.fullPath);
//console.log(' 内部路径:' + fromInfo.shortPath);
//
const subItems = fs.readdirSync(fromInfo.fullPath);
for (const subName of subItems) {
let subFullPath = path.join(fromInfo.fullPath, subName);
let subShortPath = fromInfo.shortPath + subName;
const stats = fs.statSync(subFullPath);
if (stats.isDirectory()) {
subShortPath = subShortPath + '/';
let subInfo = {
isDir: true,
fullPath: subFullPath,
shortPath: subShortPath,
};
addItem(tarFileHandler, subInfo, 0);
}
else if (stats.isFile()) {
let subInfo = {
isDir: false,
fullPath: subFullPath,
shortPath: subShortPath,
};
addItem(tarFileHandler, subInfo, stats.size);
}
//只处理目录与普通文件
}
}
else {
//
////console.log('tar增加文件:' + fromInfo.fullPath);
////console.log(' 内部路径:' + fromInfo.shortPath);
//
// 写入tar 头
writeTarHeader(tarFileHandler, fromInfo.shortPath, false, fileSize);
if (fileSize == 0) {
return 0;
}
// 下面将文件内容写入到 tar 里面
const fd = fs.openSync(fromInfo.fullPath, 'r');
if (!fd) {
console.error('cannot open file: ' + fromInfo.fullPath);
return -1;
}
let readSize = 0;
let buffer = Buffer.alloc(32768);
let writeTotal = 0;
while (true) {
readSize = fs.readSync(fd, buffer, 0, 32768, null);
if (readSize > 0) {
fs.writeSync(tarFileHandler, buffer, 0, readSize, null);
writeTotal += readSize;
}
else {
break;
}
}
// 下面做512字节对齐
let outSize = writeTotal % 512;
if (outSize > 0) {
outSize = 512 - outSize;
buffer.fill(0);
fs.writeSync(tarFileHandler, buffer, 0, outSize, null);
}
//
//
fs.closeSync(fd);
}
return 0;
}
function makeTarFile(tarSourceFullPath, tarFileName) {
//console.log('start path = ' + tarSourceFullPath);
currTimeStamp = new Date().getTime();
currTimeStamp = parseInt(currTimeStamp / 1000);
const tarFileHandler = fs.openSync(tarFileName, 'w');
if (!tarFileHandler) {
console.error('cannot open file: ' + tarFileName);
return -1;
}
let rootInfo = {
isDir: true,
fullPath: tarSourceFullPath,
shortPath: '',
};
addItem(tarFileHandler, rootInfo, 0);
//
fs.closeSync(tarFileHandler);
return 0;
}
export default {
makeTarFile
};