From f0a45bf9314149f4a59611202bb6cfa5ad554824 Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sat, 13 Jun 2020 22:28:29 +0200 Subject: [PATCH 1/8] Support for label --- .gitignore | 2 + README.md | 1 + dir.js | 8 ++-- helpers.js | 17 +++++--- index.js | 25 ++++++++++-- package.json | 6 ++- run_tests.sh | 35 ++++++++++++++++ tests/fatfs-buffer.js | 95 +++++++++++++++++++++++++++++++++++++++++++ tests/label.js | 17 ++++++++ 9 files changed, 193 insertions(+), 13 deletions(-) create mode 100755 run_tests.sh create mode 100644 tests/fatfs-buffer.js create mode 100644 tests/label.js diff --git a/.gitignore b/.gitignore index 894e41c..a1824ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .DS_Store .vscode/ node_modules/ +package-lock.json +label.img \ No newline at end of file diff --git a/README.md b/README.md index e7c33bc..830f989 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ The `opts` dictionary you pass to `fatfs.createFileSystem` can contain any of th * `umask` — any bits *set* in this octal number will be *unset* in the 'mode' field from `fs.stat`–family calls. It does not affect anything else. Defaults to `process.umask()`, or `0022` if that is unavailable. * `uid` — This value will be returned as the 'uid' stat field. It does not affect anything else. Defaults to `process.getuid()`, or `0` if that is unavailable. * `gid` — This value will be returned as the 'gid' stat field. It does not affect anything else. Defaults to `process.getgid()`, or `0` if that is unavailable. +* `allowLowercaseNames` - This value disables automatic conversion from lowercase to uppercase. While it's illegal for DOS, it's required for linux lowercase labels (https://github.com/natevw/fatfs/issues/30) (Note that these are similar to the options you could use with a POSIX `mount` operation.) diff --git a/dir.js b/dir.js index 21ab498..2da1ee7 100644 --- a/dir.js +++ b/dir.js @@ -251,7 +251,7 @@ dir.init = function (vol, dirInfo, cb) { dirChain.writeToPosition(0, initialCluster, cb); }; -dir.addFile = function (vol, dirChain, entryInfo, opts, cb) { +dir.addFile = function (vol, allowLowercaseNames, dirChain, entryInfo, opts, cb) { if (typeof opts === 'function') { cb = opts; opts = {}; @@ -259,7 +259,7 @@ dir.addFile = function (vol, dirChain, entryInfo, opts, cb) { var name = entryInfo.name, entries = [], mainEntry; entries.push(mainEntry = { - Name: _.shortname(name), + Name: _.shortname(name, allowLowercaseNames), Attr: {directory:opts.dir||false}, _name: name }); @@ -328,9 +328,9 @@ dir.addFile = function (vol, dirChain, entryInfo, opts, cb) { }); }; -dir.findInDirectory = function (vol, dirChain, name, opts, cb) { +dir.findInDirectory = function (vol, dirChain, name, opts, allowLowercaseNames, cb) { var matchName = name.toUpperCase(), - tailName = (opts.prepareForCreate) ? _.shortname(name) : null, + tailName = (opts.prepareForCreate) ? _.shortname(name, allowLowercaseNames) : null, maxTail = 0; function processNext(next) { diff --git a/helpers.js b/helpers.js index 10a1cc8..9387cb5 100644 --- a/helpers.js +++ b/helpers.js @@ -71,12 +71,20 @@ exports.parseFlags = function (flags) { // TODO: these are great candidates for special test coverage! -var _snInvalid = /[^A-Z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away -exports.shortname = function (name) { +var _snInvalid = /[^A-Z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away +var _snInvalidWithLowercase = /[^A-Za-z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away +exports.shortname = function (name, allowLowercaseNames) { var lossy = false; + var regex // TODO: support preservation of case for otherwise non-lossy name! - name = name.toUpperCase().replace(/ /g, '').replace(/^\.+/, ''); - name = name.replace(_snInvalid, function () { + if (allowLowercaseNames) { + regex = _snInvalidWithLowercase + } else { + regex = _snInvalid + name = name.toUpperCase() + } + name = name.replace(/ /g, '').replace(/^\.+/, ''); + name = name.replace(regex, function () { lossy = true; return '_'; }); @@ -100,7 +108,6 @@ exports.shortname = function (name) { } else while (basis3.length < 3) basis3 += ' '; return {filename:basis8, extension:basis3, _lossy:lossy}; - return {basis:[basis8,basis3], lossy:lossy}; }; //shortname("autoexec.bat") => {basis:['AUTOEXEC','BAT'],lossy:false} //shortname("autoexecutable.batch") => {basis:['AUTOEXEC','BAT'],lossy:true} diff --git a/index.js b/index.js index 960de6a..3599479 100644 --- a/index.js +++ b/index.js @@ -18,11 +18,14 @@ exports.createFileSystem = function (volume, opts, cb) { modmode: 0111, // or `07000` umask: ('umask' in process) ? process.umask() : 0022, uid: ('getuid' in process) ? process.getuid() : 0, - gid: ('getgid' in process) ? process.getgid() : 0 + gid: ('getgid' in process) ? process.getgid() : 0, + allowLowercaseNames: false }, opts); if (!volume.writeSectors) opts.ro = true; if (opts.ro) opts.noatime = true; // natch + const allowLowercaseNames = opts.allowLowercaseNames + var fs = new events.EventEmitter(), vol = null, dir = require("./dir.js"), @@ -104,7 +107,7 @@ exports.createFileSystem = function (volume, opts, cb) { else fs._sharedEntryForSteps(steps, {}, function (e,parentInfo) { // n.b. `steps` don't include `name` if (e) cb(e); else if (!parentInfo.entry.Attr.directory) cb(S.err.NOTDIR()) - else dir.findInDirectory(vol, parentInfo.chain, name, opts, function (e,entry) { + else dir.findInDirectory(vol, parentInfo.chain, name, opts, allowLowercaseNames, function (e,entry) { if (e && !opts.prepareForCreate) cb(e); else if (e) cb(e, {missingChild:_.extend(entry, {name:name}), parent:parentInfo}); else cb(null, fs._createSharedEntry(path, entry, vol.chainForCluster(entry._firstCluster), parentInfo)); @@ -114,7 +117,7 @@ exports.createFileSystem = function (volume, opts, cb) { fs._updateEntry = dir.updateEntry.bind(dir, vol); fs._makeStat = dir.makeStat.bind(dir, vol); - fs._addFile = dir.addFile.bind(dir, vol); + fs._addFile = dir.addFile.bind(dir, vol, allowLowercaseNames); fs._initDir = dir.init.bind(dir, vol); } @@ -557,6 +560,22 @@ exports.createFileSystem = function (volume, opts, cb) { else _.delayedCall(cb, S.err.NOSYS()); }, (_n_ === '_nested_')); }; + fs.createLabel = function (name, cb) { + fs.writeFile(name, "", () => { + fs.open(name, "w", (e,_fd) => { + if (e) { + throw '_open_error_' + } else { + let fd = fileDescriptors[_fd] + fd.entry.Attr.volume_id = true + fd.entry.FstClusLO = 0 + fd.entry.FstClusHI = 0 + + fs._updateEntry(fd.entry, {}, cb); + } + }, '_nested_') + }) + }; return fs; } diff --git a/package.json b/package.json index 6747121..71f6ebf 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "description": "fs implementation on top of raw FAT16/FAT32 block source", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "label-test": "nodejs tests/label.js" + }, + "devDependencies": { + "promise-toolbox": "0.15.1" }, "repository": { "type": "git", diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..019821c --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +if ! [ -x "$(command -v blkid)" ]; then + echo 'Error: util-linux is not installed.' >&2 + exit 1 +fi + +if ! [ -x "$(command -v dosfslabel)" ]; then + echo 'Error: dosfstools is not installed.' >&2 + exit 1 +fi + +rm tests/label.img || true + +set -e + +npm run label-test + +BLKID=$(blkid tests/label.img) +DOSFSLABEL=$(dosfslabel tests/label.img) + +if ! [[ $BLKID == *'LABEL_FATBOOT="cidata"'* ]]; then + echo "blkid: LABEL_FATBOOT is invalid" + exit 1 +fi + +if ! [[ $BLKID == *'LABEL="cidata"'* ]]; then + echo "blkid: LABEL is invalid" + exit 1 +fi + +if ! [[ $DOSFSLABEL == *"cidata"* ]]; then + echo "dosfslabel: label is invalid" + exit 1 +fi \ No newline at end of file diff --git a/tests/fatfs-buffer.js b/tests/fatfs-buffer.js new file mode 100644 index 0000000..cc7350f --- /dev/null +++ b/tests/fatfs-buffer.js @@ -0,0 +1,95 @@ +// Buffer driver for [fatfs](https://github.com/natevw/fatfs). +// +// Usage: +// +// ```js +// import fatfs from 'fatfs' +// import fatfsBuffer, { init as fatfsBufferInit } from './fatfs-buffer' +// +// const buffer = fatfsBufferinit() +// +// const fs = fatfs.createFileSystem(fatfsBuffer(buffer)) +// +// fs.writeFile('/foo', 'content of foo', function (err, content) { +// if (err) { +// console.error(err) +// } +// }) + +var assert = require('assert') + +var fat16 = require('../structs').boot16 + +const SECTOR_SIZE = 512 + +const TEN_MIB = 10 * 1024 * 1024 + +// Creates a 10MB buffer and initializes it as a FAT 16 volume. +module.exports.init = ({ label = 'NO LABEL ' } = {}) => { + assert.strictEqual(typeof label, 'string') + assert.strictEqual(label.length, 11) + + const buf = Buffer.alloc(TEN_MIB) + + // https://github.com/natevw/fatfs/blob/master/structs.js + fat16.pack( + { + jmpBoot: Buffer.from('eb3c90', 'hex'), + OEMName: 'mkfs.fat', + BytsPerSec: SECTOR_SIZE, + SecPerClus: 4, + ResvdSecCnt: 1, + NumFATs: 2, + RootEntCnt: 512, + TotSec16: 20480, + Media: 248, + FATSz16: 20, + SecPerTrk: 32, + NumHeads: 64, + HiddSec: 0, + TotSec32: 0, + DrvNum: 128, + Reserved1: 0, + BootSig: 41, + VolID: 895111106, + VolLab: label, + FilSysType: 'FAT16 ', + }, + buf + ) + + // End of sector. + buf[0x1fe] = 0x55 + buf[0x1ff] = 0xaa + + // Mark sector as reserved. + buf[0x200] = 0xf8 + buf[0x201] = 0xff + buf[0x202] = 0xff + buf[0x203] = 0xff + + // Mark sector as reserved. + buf[0x2a00] = 0xf8 + buf[0x2a01] = 0xff + buf[0x2a02] = 0xff + buf[0x2a03] = 0xff + + return buf +} + +var buffer = (buffer) => { + return { + sectorSize: SECTOR_SIZE, + numSectors: Math.floor(buffer.length / SECTOR_SIZE), + readSectors: (i, target, cb) => { + buffer.copy(target, 0, i * SECTOR_SIZE) + cb() + }, + writeSectors: (i, source, cb) => { + source.copy(buffer, i * SECTOR_SIZE, 0) + cb() + }, + } +} + +module.exports.buffer = buffer \ No newline at end of file diff --git a/tests/label.js b/tests/label.js new file mode 100644 index 0000000..2fae2af --- /dev/null +++ b/tests/label.js @@ -0,0 +1,17 @@ +// import fatfsBuffer, { init as fatfsBufferInit } from './fatfs-buffer' +const promisifyAll = require('promise-toolbox').promisifyAll; +var fatfs = require("../"); +const { fatStat } = require('../structs'); +var fatfsBuffer = require('./fatfs-buffer').buffer +var fatfsBufferInit = require('./fatfs-buffer').init +var fs = require('fs') + +const buffer = fatfsBufferInit({ label: 'cidata ' }) + +const { createLabel } = promisifyAll( + fatfs.createFileSystem(fatfsBuffer(buffer), {allowLowercaseNames: true}) +) + +createLabel("cidata").then(() => { + fs.writeFileSync("tests/label.img", buffer) +}) \ No newline at end of file From a82c3334df58d83101288b67d6e569c6282befe7 Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 14 Jun 2020 00:14:03 +0200 Subject: [PATCH 2/8] Support for label --- run_tests.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/run_tests.sh b/run_tests.sh index 019821c..f78e170 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -24,12 +24,18 @@ if ! [[ $BLKID == *'LABEL_FATBOOT="cidata"'* ]]; then exit 1 fi +echo "blkid LABEL_FATBOOT valid" + if ! [[ $BLKID == *'LABEL="cidata"'* ]]; then echo "blkid: LABEL is invalid" exit 1 fi +echo "blkid LABEL valid" + if ! [[ $DOSFSLABEL == *"cidata"* ]]; then echo "dosfslabel: label is invalid" exit 1 -fi \ No newline at end of file +fi + +echo "dosfslabel LABEL valid" \ No newline at end of file From af4a6e9334fdd3ef83399581e1641d7972df1184 Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 14 Jun 2020 00:16:35 +0200 Subject: [PATCH 3/8] Remove lowercase stuff --- dir.js | 8 ++++---- helpers.js | 17 +++++------------ index.js | 9 +++------ run_tests.sh | 10 +++++----- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/dir.js b/dir.js index 2da1ee7..21ab498 100644 --- a/dir.js +++ b/dir.js @@ -251,7 +251,7 @@ dir.init = function (vol, dirInfo, cb) { dirChain.writeToPosition(0, initialCluster, cb); }; -dir.addFile = function (vol, allowLowercaseNames, dirChain, entryInfo, opts, cb) { +dir.addFile = function (vol, dirChain, entryInfo, opts, cb) { if (typeof opts === 'function') { cb = opts; opts = {}; @@ -259,7 +259,7 @@ dir.addFile = function (vol, allowLowercaseNames, dirChain, entryInfo, opts, cb) var name = entryInfo.name, entries = [], mainEntry; entries.push(mainEntry = { - Name: _.shortname(name, allowLowercaseNames), + Name: _.shortname(name), Attr: {directory:opts.dir||false}, _name: name }); @@ -328,9 +328,9 @@ dir.addFile = function (vol, allowLowercaseNames, dirChain, entryInfo, opts, cb) }); }; -dir.findInDirectory = function (vol, dirChain, name, opts, allowLowercaseNames, cb) { +dir.findInDirectory = function (vol, dirChain, name, opts, cb) { var matchName = name.toUpperCase(), - tailName = (opts.prepareForCreate) ? _.shortname(name, allowLowercaseNames) : null, + tailName = (opts.prepareForCreate) ? _.shortname(name) : null, maxTail = 0; function processNext(next) { diff --git a/helpers.js b/helpers.js index 9387cb5..10a1cc8 100644 --- a/helpers.js +++ b/helpers.js @@ -71,20 +71,12 @@ exports.parseFlags = function (flags) { // TODO: these are great candidates for special test coverage! -var _snInvalid = /[^A-Z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away -var _snInvalidWithLowercase = /[^A-Za-z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away -exports.shortname = function (name, allowLowercaseNames) { +var _snInvalid = /[^A-Z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away +exports.shortname = function (name) { var lossy = false; - var regex // TODO: support preservation of case for otherwise non-lossy name! - if (allowLowercaseNames) { - regex = _snInvalidWithLowercase - } else { - regex = _snInvalid - name = name.toUpperCase() - } - name = name.replace(/ /g, '').replace(/^\.+/, ''); - name = name.replace(regex, function () { + name = name.toUpperCase().replace(/ /g, '').replace(/^\.+/, ''); + name = name.replace(_snInvalid, function () { lossy = true; return '_'; }); @@ -108,6 +100,7 @@ exports.shortname = function (name, allowLowercaseNames) { } else while (basis3.length < 3) basis3 += ' '; return {filename:basis8, extension:basis3, _lossy:lossy}; + return {basis:[basis8,basis3], lossy:lossy}; }; //shortname("autoexec.bat") => {basis:['AUTOEXEC','BAT'],lossy:false} //shortname("autoexecutable.batch") => {basis:['AUTOEXEC','BAT'],lossy:true} diff --git a/index.js b/index.js index 3599479..5369343 100644 --- a/index.js +++ b/index.js @@ -18,14 +18,11 @@ exports.createFileSystem = function (volume, opts, cb) { modmode: 0111, // or `07000` umask: ('umask' in process) ? process.umask() : 0022, uid: ('getuid' in process) ? process.getuid() : 0, - gid: ('getgid' in process) ? process.getgid() : 0, - allowLowercaseNames: false + gid: ('getgid' in process) ? process.getgid() : 0 }, opts); if (!volume.writeSectors) opts.ro = true; if (opts.ro) opts.noatime = true; // natch - const allowLowercaseNames = opts.allowLowercaseNames - var fs = new events.EventEmitter(), vol = null, dir = require("./dir.js"), @@ -107,7 +104,7 @@ exports.createFileSystem = function (volume, opts, cb) { else fs._sharedEntryForSteps(steps, {}, function (e,parentInfo) { // n.b. `steps` don't include `name` if (e) cb(e); else if (!parentInfo.entry.Attr.directory) cb(S.err.NOTDIR()) - else dir.findInDirectory(vol, parentInfo.chain, name, opts, allowLowercaseNames, function (e,entry) { + else dir.findInDirectory(vol, parentInfo.chain, name, opts, function (e,entry) { if (e && !opts.prepareForCreate) cb(e); else if (e) cb(e, {missingChild:_.extend(entry, {name:name}), parent:parentInfo}); else cb(null, fs._createSharedEntry(path, entry, vol.chainForCluster(entry._firstCluster), parentInfo)); @@ -117,7 +114,7 @@ exports.createFileSystem = function (volume, opts, cb) { fs._updateEntry = dir.updateEntry.bind(dir, vol); fs._makeStat = dir.makeStat.bind(dir, vol); - fs._addFile = dir.addFile.bind(dir, vol, allowLowercaseNames); + fs._addFile = dir.addFile.bind(dir, vol); fs._initDir = dir.init.bind(dir, vol); } diff --git a/run_tests.sh b/run_tests.sh index f78e170..115a5ad 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -24,18 +24,18 @@ if ! [[ $BLKID == *'LABEL_FATBOOT="cidata"'* ]]; then exit 1 fi -echo "blkid LABEL_FATBOOT valid" +echo "blkid: LABEL_FATBOOT is valid" -if ! [[ $BLKID == *'LABEL="cidata"'* ]]; then +if ! [[ $BLKID == *'LABEL="CIDATA"'* ]]; then echo "blkid: LABEL is invalid" exit 1 fi -echo "blkid LABEL valid" +echo "blkid: LABEL is valid" -if ! [[ $DOSFSLABEL == *"cidata"* ]]; then +if ! [[ $DOSFSLABEL == *"CIDATA"* ]]; then echo "dosfslabel: label is invalid" exit 1 fi -echo "dosfslabel LABEL valid" \ No newline at end of file +echo "dosfslabel: label is valid" \ No newline at end of file From 37023948b90debaddd79498a5333a5d744ebb6fd Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 14 Jun 2020 00:33:24 +0200 Subject: [PATCH 4/8] Remove lowercase stuff --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 830f989..e7c33bc 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ The `opts` dictionary you pass to `fatfs.createFileSystem` can contain any of th * `umask` — any bits *set* in this octal number will be *unset* in the 'mode' field from `fs.stat`–family calls. It does not affect anything else. Defaults to `process.umask()`, or `0022` if that is unavailable. * `uid` — This value will be returned as the 'uid' stat field. It does not affect anything else. Defaults to `process.getuid()`, or `0` if that is unavailable. * `gid` — This value will be returned as the 'gid' stat field. It does not affect anything else. Defaults to `process.getgid()`, or `0` if that is unavailable. -* `allowLowercaseNames` - This value disables automatic conversion from lowercase to uppercase. While it's illegal for DOS, it's required for linux lowercase labels (https://github.com/natevw/fatfs/issues/30) (Note that these are similar to the options you could use with a POSIX `mount` operation.) From a412f339f9179fd9cc46b8b2b0886161bd05b342 Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 14 Jun 2020 01:00:23 +0200 Subject: [PATCH 5/8] Finish PR --- tests/fatfs-buffer.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/tests/fatfs-buffer.js b/tests/fatfs-buffer.js index cc7350f..b798e13 100644 --- a/tests/fatfs-buffer.js +++ b/tests/fatfs-buffer.js @@ -1,20 +1,4 @@ -// Buffer driver for [fatfs](https://github.com/natevw/fatfs). -// -// Usage: -// -// ```js -// import fatfs from 'fatfs' -// import fatfsBuffer, { init as fatfsBufferInit } from './fatfs-buffer' -// -// const buffer = fatfsBufferinit() -// -// const fs = fatfs.createFileSystem(fatfsBuffer(buffer)) -// -// fs.writeFile('/foo', 'content of foo', function (err, content) { -// if (err) { -// console.error(err) -// } -// }) +//From https://github.com/vatesfr/xen-orchestra/blob/9f0b22d3e9c4672d96cb3f63b1e0fd42609e2406/packages/xo-server/src/fatfs-buffer.js var assert = require('assert') From 8999e85707b8c148607acff843a6e5a0ac7135a2 Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Sun, 14 Jun 2020 01:18:14 +0200 Subject: [PATCH 6/8] Finish PR --- package.json | 2 +- run_tests.sh | 2 +- tests/label.js | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 71f6ebf..5017e8e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "label-test": "nodejs tests/label.js" + "label-testcase": "nodejs tests/label.js" }, "devDependencies": { "promise-toolbox": "0.15.1" diff --git a/run_tests.sh b/run_tests.sh index 115a5ad..78a415d 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -14,7 +14,7 @@ rm tests/label.img || true set -e -npm run label-test +npm run label-testcase BLKID=$(blkid tests/label.img) DOSFSLABEL=$(dosfslabel tests/label.img) diff --git a/tests/label.js b/tests/label.js index 2fae2af..0b0a62d 100644 --- a/tests/label.js +++ b/tests/label.js @@ -1,7 +1,5 @@ -// import fatfsBuffer, { init as fatfsBufferInit } from './fatfs-buffer' const promisifyAll = require('promise-toolbox').promisifyAll; var fatfs = require("../"); -const { fatStat } = require('../structs'); var fatfsBuffer = require('./fatfs-buffer').buffer var fatfsBufferInit = require('./fatfs-buffer').init var fs = require('fs') From 144d1583cc258060e0b54ca996e05b02683dc5ac Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Tue, 21 Jul 2020 21:35:00 +0200 Subject: [PATCH 7/8] Fix PR comments --- .gitignore | 2 +- index.js | 22 ++++++------ package.json | 3 -- run_tests.sh | 10 ++---- tests/fatfs-buffer.js | 79 ------------------------------------------- tests/label.js | 15 +++----- 6 files changed, 18 insertions(+), 113 deletions(-) delete mode 100644 tests/fatfs-buffer.js diff --git a/.gitignore b/.gitignore index a1824ff..2fdf88a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .vscode/ node_modules/ package-lock.json -label.img \ No newline at end of file +tests/label.img \ No newline at end of file diff --git a/index.js b/index.js index 5369343..5647874 100644 --- a/index.js +++ b/index.js @@ -558,19 +558,17 @@ exports.createFileSystem = function (volume, opts, cb) { }, (_n_ === '_nested_')); }; fs.createLabel = function (name, cb) { - fs.writeFile(name, "", () => { - fs.open(name, "w", (e,_fd) => { - if (e) { - throw '_open_error_' - } else { - let fd = fileDescriptors[_fd] - fd.entry.Attr.volume_id = true - fd.entry.FstClusLO = 0 - fd.entry.FstClusHI = 0 + fs.open(name, "a", (e,_fd) => { + if (e) { + throw '_open_error_' + } else { + let fd = fileDescriptors[_fd] + fd.entry.Attr.volume_id = true + fd.entry.FstClusLO = 0 + fd.entry.FstClusHI = 0 - fs._updateEntry(fd.entry, {}, cb); - } - }, '_nested_') + fs._updateEntry(fd.entry, {}, cb); + } }) }; diff --git a/package.json b/package.json index 5017e8e..52a125c 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,6 @@ "test": "echo \"Error: no test specified\" && exit 1", "label-testcase": "nodejs tests/label.js" }, - "devDependencies": { - "promise-toolbox": "0.15.1" - }, "repository": { "type": "git", "url": "https://github.com/natevw/fatfs" diff --git a/run_tests.sh b/run_tests.sh index 78a415d..650e7ee 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -14,18 +14,14 @@ rm tests/label.img || true set -e +dd if=/dev/zero of=tests/label.img bs=1M count=10 +mkfs.vfat tests/label.img + npm run label-testcase BLKID=$(blkid tests/label.img) DOSFSLABEL=$(dosfslabel tests/label.img) -if ! [[ $BLKID == *'LABEL_FATBOOT="cidata"'* ]]; then - echo "blkid: LABEL_FATBOOT is invalid" - exit 1 -fi - -echo "blkid: LABEL_FATBOOT is valid" - if ! [[ $BLKID == *'LABEL="CIDATA"'* ]]; then echo "blkid: LABEL is invalid" exit 1 diff --git a/tests/fatfs-buffer.js b/tests/fatfs-buffer.js deleted file mode 100644 index b798e13..0000000 --- a/tests/fatfs-buffer.js +++ /dev/null @@ -1,79 +0,0 @@ -//From https://github.com/vatesfr/xen-orchestra/blob/9f0b22d3e9c4672d96cb3f63b1e0fd42609e2406/packages/xo-server/src/fatfs-buffer.js - -var assert = require('assert') - -var fat16 = require('../structs').boot16 - -const SECTOR_SIZE = 512 - -const TEN_MIB = 10 * 1024 * 1024 - -// Creates a 10MB buffer and initializes it as a FAT 16 volume. -module.exports.init = ({ label = 'NO LABEL ' } = {}) => { - assert.strictEqual(typeof label, 'string') - assert.strictEqual(label.length, 11) - - const buf = Buffer.alloc(TEN_MIB) - - // https://github.com/natevw/fatfs/blob/master/structs.js - fat16.pack( - { - jmpBoot: Buffer.from('eb3c90', 'hex'), - OEMName: 'mkfs.fat', - BytsPerSec: SECTOR_SIZE, - SecPerClus: 4, - ResvdSecCnt: 1, - NumFATs: 2, - RootEntCnt: 512, - TotSec16: 20480, - Media: 248, - FATSz16: 20, - SecPerTrk: 32, - NumHeads: 64, - HiddSec: 0, - TotSec32: 0, - DrvNum: 128, - Reserved1: 0, - BootSig: 41, - VolID: 895111106, - VolLab: label, - FilSysType: 'FAT16 ', - }, - buf - ) - - // End of sector. - buf[0x1fe] = 0x55 - buf[0x1ff] = 0xaa - - // Mark sector as reserved. - buf[0x200] = 0xf8 - buf[0x201] = 0xff - buf[0x202] = 0xff - buf[0x203] = 0xff - - // Mark sector as reserved. - buf[0x2a00] = 0xf8 - buf[0x2a01] = 0xff - buf[0x2a02] = 0xff - buf[0x2a03] = 0xff - - return buf -} - -var buffer = (buffer) => { - return { - sectorSize: SECTOR_SIZE, - numSectors: Math.floor(buffer.length / SECTOR_SIZE), - readSectors: (i, target, cb) => { - buffer.copy(target, 0, i * SECTOR_SIZE) - cb() - }, - writeSectors: (i, source, cb) => { - source.copy(buffer, i * SECTOR_SIZE, 0) - cb() - }, - } -} - -module.exports.buffer = buffer \ No newline at end of file diff --git a/tests/label.js b/tests/label.js index 0b0a62d..9fb6d0e 100644 --- a/tests/label.js +++ b/tests/label.js @@ -1,15 +1,8 @@ -const promisifyAll = require('promise-toolbox').promisifyAll; var fatfs = require("../"); -var fatfsBuffer = require('./fatfs-buffer').buffer -var fatfsBufferInit = require('./fatfs-buffer').init -var fs = require('fs') +var createDriverSync = require("../img_volume").createDriverSync -const buffer = fatfsBufferInit({ label: 'cidata ' }) +const buffer = createDriverSync("tests/label.img") -const { createLabel } = promisifyAll( - fatfs.createFileSystem(fatfsBuffer(buffer), {allowLowercaseNames: true}) -) +const fs = fatfs.createFileSystem(buffer, {allowLowercaseNames: true}) -createLabel("cidata").then(() => { - fs.writeFileSync("tests/label.img", buffer) -}) \ No newline at end of file +fs.createLabel("cidata", () => {}) \ No newline at end of file From d8b9cb71ea9e7edfa5a6e7dbb693a144a740bcdd Mon Sep 17 00:00:00 2001 From: Andrzej Ressel Date: Tue, 21 Jul 2020 23:41:24 +0200 Subject: [PATCH 8/8] Fix PR comments --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 5647874..09c7b0f 100644 --- a/index.js +++ b/index.js @@ -558,9 +558,9 @@ exports.createFileSystem = function (volume, opts, cb) { }, (_n_ === '_nested_')); }; fs.createLabel = function (name, cb) { - fs.open(name, "a", (e,_fd) => { + fs.open(name, "a", (e, _fd) => { if (e) { - throw '_open_error_' + cb(e); } else { let fd = fileDescriptors[_fd] fd.entry.Attr.volume_id = true