Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Implement createWriteStream for Linux #15

Merged
merged 3 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const fs = require('fs')
const { spawn } = require('child_process')
const { spawn, spawnSync } = require('child_process')
const EventEmitter = require('events')
const binding = require('./build/Release/fs_admin.node')
const fsAdmin = module.exports
Expand Down Expand Up @@ -149,6 +149,45 @@ switch (process.platform) {
}
})
break

case 'linux':
Object.assign(fsAdmin, {
clearAuthorizationCache () {
spawnSync('/bin/pkcheck', ['--revoke-temp'])
},

createWriteStream (filePath) {
// Prompt for credentials synchronously to avoid creating multiple simultaneous prompts.
if (!fsAdmin.testMode && spawnSync('/usr/bin/pkexec', ['/bin/dd']).status !== 0) {
const result = new EventEmitter()
result.write = result.end = function () {}
process.nextTick(() => result.emit('error', new Error('Failed to obtain credentials')))
return result
}

const dd = fsAdmin.testMode
? spawn('/bin/dd', ['of=' + filePath])
: spawn('/usr/bin/pkexec', ['/bin/dd', 'of=' + filePath])

const stream = new EventEmitter()
stream.write = (chunk, encoding, callback) => {
dd.stdin.write(chunk, encoding, callback)
}
stream.end = (callback) => {
if (callback) stream.on('finish', callback)
dd.stdin.end()
}
dd.on('exit', (exitCode) => {
if (exitCode !== 0) {
stream.emit('error', new Error('dd exited with code ' + exitCode))
}
stream.emit('finish')
})

return stream
}
})
break
}

function wrapCallback (commandName, callback) {
Expand Down
14 changes: 9 additions & 5 deletions test/fs-admin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ const fsAdmin = require('..')
// Comment this out to test with actual privilege escalation.
fsAdmin.testMode = true

if (process.platform !== 'win32' && process.platform !== 'darwin') {
process.exit(0)
}

describe('fs-admin', function () {
let dirPath, filePath

Expand All @@ -23,7 +19,7 @@ describe('fs-admin', function () {
if (!fsAdmin.testMode) this.timeout(10000)

describe('createWriteStream', () => {
if (process.platform !== 'darwin') return
if (process.platform === 'win32') return

it('writes to the given file as the admin user', (done) => {
fs.writeFileSync(filePath, '')
Expand Down Expand Up @@ -74,6 +70,8 @@ describe('fs-admin', function () {
})

describe('makeTree', () => {
if (process.platform === 'linux') return

it('creates a directory at the given path as the admin user', (done) => {
const pathToCreate = path.join(dirPath, 'dir1', 'dir2', 'dir3')

Expand All @@ -92,6 +90,8 @@ describe('fs-admin', function () {
})

describe('unlink', () => {
if (process.platform === 'linux') return

it('deletes the given file as the admin user', (done) => {
fs.writeFileSync(filePath, '')

Expand Down Expand Up @@ -126,6 +126,8 @@ describe('fs-admin', function () {
})

describe('symlink', () => {
if (process.platform === 'linux') return

it('creates a symlink at the given path as the admin user', (done) => {
fsAdmin.symlink(__filename, filePath, (error) => {
assert.strictEqual(error, null)
Expand All @@ -141,6 +143,8 @@ describe('fs-admin', function () {
})

describe('recursiveCopy', () => {
if (process.platform === 'linux') return

it('copies the given folder to the given location as the admin user', (done) => {
const sourcePath = path.join(dirPath, 'src-dir')
fs.mkdirSync(sourcePath)
Expand Down