mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-10-12 02:24:05 +00:00
256 lines
6.2 KiB
JavaScript
256 lines
6.2 KiB
JavaScript
// see http://staff.washington.edu/dittrich/misc/fatgen103.pdf
|
|
// and http://www.cse.scu.edu/~tschwarz/COEN252_09/Lectures/FAT.html
|
|
|
|
var _ = require('struct-fu'),
|
|
__ = require("./helpers.js");
|
|
|
|
var bootBase = _.struct([
|
|
_.byte('jmpBoot', 3),
|
|
_.char('OEMName', 8),
|
|
_.uint16le('BytsPerSec'),
|
|
_.uint8('SecPerClus'),
|
|
_.uint16le('ResvdSecCnt'), // Rsvd in table, but Resvd in calcs…
|
|
_.uint8('NumFATs'),
|
|
_.uint16le('RootEntCnt'),
|
|
_.uint16le('TotSec16'),
|
|
_.uint8('Media'),
|
|
_.uint16le('FATSz16'),
|
|
_.uint16le('SecPerTrk'),
|
|
_.uint16le('NumHeads'),
|
|
_.uint32le('HiddSec'),
|
|
_.uint32le('TotSec32')
|
|
]);
|
|
|
|
var bootInfo = _.struct([
|
|
_.uint8('DrvNum'),
|
|
_.uint8('Reserved1'),
|
|
_.uint8('BootSig'),
|
|
_.uint32le('VolID'),
|
|
_.char('VolLab', 11),
|
|
_.char('FilSysType', 8)
|
|
]);
|
|
|
|
exports.boot16 = _.struct([
|
|
bootBase,
|
|
bootInfo
|
|
]);
|
|
|
|
exports.boot32 = _.struct([
|
|
bootBase,
|
|
_.uint32le('FATSz32'),
|
|
_.struct('ExtFlags', [
|
|
_.ubit('NumActiveFAT', 4),
|
|
_.ubit('_reserved1', 3),
|
|
_.bool('MirroredFAT'),
|
|
_.ubit('_reserved2', 8)
|
|
].reverse()),
|
|
_.struct('FSVer', [
|
|
_.uint8('Major'),
|
|
_.uint8('Minor')
|
|
]),
|
|
_.uint32le('RootClus'),
|
|
_.uint16le('FSInfo'),
|
|
_.uint16le('BkBootSec'),
|
|
_.byte('Reserved', 12),
|
|
bootInfo
|
|
]);
|
|
|
|
|
|
var _time = _.struct([
|
|
_.ubit('hours',5),
|
|
_.ubit('minutes',6),
|
|
_.ubit('seconds_2',5)
|
|
]), time = {
|
|
valueFromBytes: function (buf, off) {
|
|
off || (off = {bytes:0});
|
|
|
|
var _buf = __.bufferFrom([buf[off.bytes+1], buf[off.bytes+0]]),
|
|
val = _time.valueFromBytes(_buf);
|
|
off.bytes += this.size;
|
|
return val;
|
|
},
|
|
bytesFromValue: function (val, buf, off) {
|
|
val || (val = {hours:0, minutes:0, seconds_2:0});
|
|
buf || (buf = __.allocBuffer(this.size));
|
|
off || (off = {bytes:0});
|
|
|
|
var _buf = _time.bytesFromValue(val);
|
|
buf[off.bytes+1] = _buf[0];
|
|
buf[off.bytes+0] = _buf[1];
|
|
off.bytes += this.size;
|
|
return buf;
|
|
},
|
|
size: _time.size
|
|
};
|
|
|
|
var _date = _.struct([
|
|
_.ubit('year',7),
|
|
_.ubit('month',4),
|
|
_.ubit('day',5)
|
|
]), date = {
|
|
valueFromBytes: function (buf, off) {
|
|
off || (off = {bytes:0});
|
|
|
|
var _buf = __.bufferFrom([buf[off.bytes+1], buf[off.bytes+0]]),
|
|
val = _date.valueFromBytes(_buf);
|
|
off.bytes += this.size;
|
|
return val;
|
|
},
|
|
bytesFromValue: function (val, buf, off) {
|
|
val || (val = {year:0, month:0, day:0});
|
|
buf || (buf = __.allocBuffer(this.size));
|
|
off || (off = {bytes:0});
|
|
|
|
var _buf = _date.bytesFromValue(val);
|
|
buf[off.bytes+1] = _buf[0];
|
|
buf[off.bytes+0] = _buf[1];
|
|
off.bytes += this.size;
|
|
return buf;
|
|
},
|
|
size: _date.size
|
|
};
|
|
|
|
exports.dirEntry = _.struct([
|
|
_.struct('Name', [
|
|
_.char('filename',8),
|
|
_.char('extension',3)
|
|
]),
|
|
_.struct('Attr', [
|
|
_.bool('readonly'),
|
|
_.bool('hidden'),
|
|
_.bool('system'),
|
|
_.bool('volume_id'),
|
|
_.bool('directory'),
|
|
_.bool('archive'),
|
|
_.ubit('reserved', 2)
|
|
].reverse()),
|
|
_.byte('NTRes', 1),
|
|
_.uint8('CrtTimeTenth'),
|
|
_.struct('CrtTime', [time]),
|
|
_.struct('CrtDate', [date]),
|
|
_.struct('LstAccDate', [date]),
|
|
_.uint16le('FstClusHI'),
|
|
_.struct('WrtTime', [time]),
|
|
_.struct('WrtDate', [date]),
|
|
_.uint16le('FstClusLO'),
|
|
_.uint32le('FileSize')
|
|
]);
|
|
exports.entryDoneFlag = 0x00;
|
|
exports.entryFreeFlag = 0xE5;
|
|
exports.entryIsE5Flag = 0x05;
|
|
|
|
exports.dirEntry_simple = _.struct([
|
|
_.struct('Name', [
|
|
_.char('filename',8),
|
|
_.char('extension',3)
|
|
]),
|
|
_.padTo(exports.dirEntry.size)
|
|
/*
|
|
_.uint8('Attr_raw'),
|
|
_.byte('NTRes', 1),
|
|
_.byte('Crt_raw', 1+2+2),
|
|
_.byte('Lst_raw', 2),
|
|
_.uint16le('FstClusHI'),
|
|
_.byte('Wrt_raw', 2+2),
|
|
_.uint16le('FstClusLO'),
|
|
_.uint32le('FileSize')
|
|
*/
|
|
]);
|
|
|
|
|
|
exports.lastLongFlag = 0x40;
|
|
exports.longDirFlag = 0x0F;
|
|
exports.longDirEntry = _.struct([
|
|
_.uint8('Ord'),
|
|
_.char16le('Name1', 10),
|
|
_.uint8('Attr_raw'),
|
|
_.uint8('Type'),
|
|
_.uint8('Chksum'),
|
|
_.char16le('Name2', 12),
|
|
_.uint16le('FstClusLO'),
|
|
_.char16le('Name3', 4)
|
|
]);
|
|
|
|
if (exports.longDirEntry.size !== exports.dirEntry.size) throw Error("Structs ain't right!");
|
|
|
|
exports.fatField = {
|
|
'fat12': _.struct('Status', [
|
|
_.ubit('field0bc', 8),
|
|
_.ubit('field1c', 4),
|
|
_.ubit('field0a', 4),
|
|
_.ubit('field1ab', 8),
|
|
]),
|
|
'fat16': _.uint16le('Status'),
|
|
'fat32': _.uint32le('Status') // more properly this 4 bits reserved + uint28le
|
|
};
|
|
|
|
exports.fatPrefix = {
|
|
'fat12': 0xF00,
|
|
'fat16': 0xFF00,
|
|
'fat32': 0x0FFFFF00
|
|
};
|
|
|
|
exports.fatStat = {
|
|
free: 0x00,
|
|
_undef: 0x01,
|
|
rsvMin: 0xF0,
|
|
bad: 0xF7,
|
|
eofMin: 0xF8,
|
|
eof: 0xFF
|
|
};
|
|
|
|
exports._I = {
|
|
RUSR: 0400,
|
|
WUSR: 0200,
|
|
XUSR: 0100,
|
|
|
|
RGRP: 0040,
|
|
WGRP: 0020,
|
|
XGRP: 0010,
|
|
|
|
ROTH: 0004,
|
|
WOTH: 0002,
|
|
XOTH: 0001,
|
|
|
|
SUID: 04000,
|
|
SGID: 02000,
|
|
SVTX: 01000,
|
|
|
|
FDIR: 040000,
|
|
FREG: 0100000,
|
|
};
|
|
|
|
exports._I.RWXU = exports._I.RUSR | exports._I.WUSR | exports._I.XUSR;
|
|
exports._I.RWXG = exports._I.RGRP | exports._I.WGRP | exports._I.XGRP;
|
|
exports._I.RWXO = exports._I.ROTH | exports._I.WOTH | exports._I.XOTH;
|
|
exports._I._sss = exports._I.SUID | exports._I.SGID | exports._I.SVTX;
|
|
exports._I._chmoddable = exports._I.RWXU | exports._I.RWXG | exports._I.RWXO | exports._I._sss;
|
|
|
|
var _errors = {
|
|
IO: "Input/output error",
|
|
NOENT: "No such file or directory",
|
|
INVAL: "Invalid argument",
|
|
EXIST: "File exists",
|
|
NAMETOOLONG: "Filename too long",
|
|
NOSPC: "No space left on device",
|
|
NOSYS: "Function not supported",
|
|
ROFS: "ROFLCopter file system",
|
|
NOTDIR: "Not a directory",
|
|
BADF: "Bad file descriptor",
|
|
EXIST: "File exists",
|
|
ISDIR: "Is a directory",
|
|
ACCES: "Permission denied",
|
|
NOSYS: "Function not implemented",
|
|
_TODO: "Not implemented yet!"
|
|
};
|
|
|
|
exports.err = {};
|
|
Object.keys(_errors).forEach(function (sym) {
|
|
var msg = _errors[sym];
|
|
exports.err[sym] = function () {
|
|
var e = new Error(msg);
|
|
e.code = sym;
|
|
return e;
|
|
};
|
|
});
|