Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copying fifos hangs. #727

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e17d624
Don't attempt to copy fifos.
bruce-one May 31, 2017
52c412f
Avoid fifos via symlinks.
bruce-one May 31, 2017
e4a911d
Better replicate cp during direct fifo copies.
bruce-one May 31, 2017
eaaa40a
Bugfix: don't break offset during copies.
bruce-one May 31, 2017
476d4b4
Test fix, use printf for osx not echo.
bruce-one Jun 1, 2017
c71edc2
Check exec exit code to fix tests on Windows.
bruce-one Jun 2, 2017
d469212
Skip fifo tests on Windows.
bruce-one Jun 2, 2017
5689dc0
Typo.
bruce-one Jun 2, 2017
777fe04
Shell out to create fifos during recursive copy.
bruce-one Jun 19, 2017
8fa217b
Handle "recursive" flag for special non-files.
bruce-one Jun 19, 2017
18c513e
Cleanup.
bruce-one Jun 19, 2017
be93375
Error messages.
bruce-one Jun 19, 2017
599a2c5
mknod fails without root.
bruce-one Jun 19, 2017
2d3af53
Linting.
bruce-one Jun 19, 2017
d942f3f
Permissions on special files.
bruce-one Jun 19, 2017
fad43aa
Logging.
bruce-one Jun 19, 2017
e6760bb
Lint.
bruce-one Jun 19, 2017
045c290
chown and chmod special files.
bruce-one Jun 19, 2017
40518f7
Use execFileSync for safety and simplicity.
bruce-one Jun 20, 2017
c69ddc3
Use mkfifo for fifo creation due for OSX compat.
bruce-one Jun 20, 2017
b2932cf
Replace unix specific code with warning.
bruce-one Jun 21, 2017
6a4a6a0
Log that special files were skipped.
bruce-one Jun 22, 2017
f7957bf
Revert "Log that special files were skipped."
bruce-one Jun 22, 2017
a4e5411
Doc.
bruce-one Jun 22, 2017
117894c
Treat special files the same whether recursive or not.
bruce-one Jun 22, 2017
48a0198
Doc.
bruce-one Jun 22, 2017
0d70322
Build doc.
bruce-one Jun 22, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/cp.js
Expand Up @@ -34,7 +34,9 @@ function copyFileSync(srcFile, destFile, options) {
// If we're here, destFile probably doesn't exist, so just do a normal copy
}

if (fs.lstatSync(srcFile).isSymbolicLink() && !options.followsymlink) {
var srcFileStat = fs.lstatSync(srcFile);

if (srcFileStat.isSymbolicLink() && !options.followsymlink) {
try {
fs.lstatSync(destFile);
common.unlinkSync(destFile); // re-link it
Expand Down Expand Up @@ -67,7 +69,7 @@ function copyFileSync(srcFile, destFile, options) {
}

while (bytesRead === bufLength) {
bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos);
bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos || -1);
fs.writeSync(fdw, buf, 0, bytesRead);
pos += bytesRead;
}
Expand Down Expand Up @@ -139,16 +141,20 @@ function cpdirSyncRecursive(sourceDir, destDir, currentDepth, opts) {
srcFileStat = fs.statSync(srcFile);
if (srcFileStat.isDirectory()) {
cpdirSyncRecursive(srcFile, destFile, currentDepth, opts);
} else {
} else if (srcFileStat.isFile() || srcFileStat.isCharacterDevice() || srcFileStat.isBlockDevice()) {
copyFileSync(srcFile, destFile, opts);
} else {
common.log('copyFileSync: skipping non-file (' + srcFile + ')');
}
} else {
} else if (srcFileStat.isFile() || srcFileStat.isCharacterDevice() || srcFileStat.isBlockDevice()) {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
if (fs.existsSync(destFile) && opts.no_force) {
common.log('skipping existing file: ' + files[i]);
} else {
copyFileSync(srcFile, destFile, opts);
}
} else {
common.log('copyFileSync: skipping non-file (' + srcFile + ')');
}
} // for files
} // cpdirSyncRecursive
Expand Down
73 changes: 73 additions & 0 deletions test/cp.js
Expand Up @@ -755,3 +755,76 @@ test('should not overwrite recently created files (not give error no-force mode)
// Ensure First file is copied
t.is(shell.cat(`${t.context.tmp}/file1`).toString(), 'test1');
});

test('should not attempt to copy fifos in directories', t => {
shell.mkdir(`${t.context.tmp}/dir`);
try {
shell.exec(`mkfifo ${t.context.tmp}/dir/fifo`);
} catch (e) {
console.warn('Exception trying to create fifo. Skipping fifo copy test.');
return;
}
shell.cp('resources/file1', `${t.context.tmp}/dir`);
t.truthy(fs.existsSync(`${t.context.tmp}/dir/fifo`));
const result = shell.cp('-r', `${t.context.tmp}/dir`, `${t.context.tmp}/cp`);
t.falsy(shell.error());
t.is(result.code, 0);
t.is(shell.cat(`${t.context.tmp}/cp/file1`).toString(), 'test1');
t.falsy(fs.existsSync(`${t.context.tmp}/cp/fifo`));
});

test('should not attempt to copy fifos via symlinks in directories', t => {
shell.mkdir(`${t.context.tmp}/dir`);
try {
shell.exec(`mkfifo ${t.context.tmp}/dir/fifo`);
} catch (e) {
console.warn('Exception trying to create fifo. Skipping fifo copy test.');
return;
}
shell.cp('resources/file1', `${t.context.tmp}/dir`);
t.truthy(fs.existsSync(`${t.context.tmp}/dir/fifo`));
shell.pushd(`${t.context.tmp}/dir`);
fs.symlinkSync('fifo', 'symFifo');
shell.popd();
const result = shell.cp('-rL', `${t.context.tmp}/dir`, `${t.context.tmp}/cp`);
t.falsy(shell.error());
t.is(result.code, 0);
t.is(shell.cat(`${t.context.tmp}/cp/file1`).toString(), 'test1');
t.falsy(fs.existsSync(`${t.context.tmp}/cp/fifo`));
t.falsy(fs.existsSync(`${t.context.tmp}/cp/symFifo`));
});

test('should copy fifos directly', t => {
try {
shell.exec(`mkfifo ${t.context.tmp}/fifo`);
shell.exec(`printf test1 > ${t.context.tmp}/fifo`, { async: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to see shx echo -n test1 here. Appveyor may have the command, but it may not be consistent with unix printf, and I don't think it's available by default on Windows systems.

Copy link
Author

@bruce-one bruce-one Jun 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iirc, osx's echo doesn't support the -n... (Which was why I changed it initially)

Also worth noting named pipes aren't supported directly by Windows (only via cygwin etc, which didn't appear reliable)

(Could match the \n though if echo is preferred)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iirc, osx's echo doesn't support the -n... (Which was why I changed it initially)

shx echo is platform agnostic, so it runs on OS X, Win, and Linux. The behavior is guaranteed to be the same across all machines, which is what you want out of an external dependency.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah :-) good point :-)

Is it possible to easily shell out to shelljs's echo implementation? (I've shelled out here because the event loop is blocked by the cp, so need a way to get data into the fifo in the background; and atm this is shelling out to the /bin/sh impl (iirc?) and using it's echo/printf (although maybe there's a better way?)).

} catch (e) {
console.warn('Exception trying to create fifo. Skipping fifo copy test.');
return;
}
t.truthy(fs.existsSync(`${t.context.tmp}/fifo`));
const result = shell.cp(`${t.context.tmp}/fifo`, `${t.context.tmp}/newFifo`);
t.falsy(shell.error());
t.is(result.code, 0);
t.is(shell.cat(`${t.context.tmp}/newFifo`).toString(), 'test1');
t.falsy(fs.existsSync(`${t.context.tmp}/cp/fifo`));
});

test('should copy fifos directly via symlinks', t => {
try {
shell.exec(`mkfifo ${t.context.tmp}/fifo`);
shell.exec(`printf test1 > ${t.context.tmp}/fifo`, { async: true });
} catch (e) {
console.warn('Exception trying to create fifo. Skipping fifo copy test.');
return;
}
shell.pushd(t.context.tmp);
fs.symlinkSync('fifo', 'symFifo');
shell.popd();
t.truthy(fs.existsSync(`${t.context.tmp}/symFifo`));
const result = shell.cp(`${t.context.tmp}/symFifo`, `${t.context.tmp}/newFifo`);
t.falsy(shell.error());
t.is(result.code, 0);
t.is(shell.cat(`${t.context.tmp}/newFifo`).toString(), 'test1');
t.falsy(fs.existsSync(`${t.context.tmp}/cp/fifo`));
});