1// Flags: --expose-internals 2// Copyright Joyent, Inc. and other Node contributors. 3// 4// Permission is hereby granted, free of charge, to any person obtaining a 5// copy of this software and associated documentation files (the 6// "Software"), to deal in the Software without restriction, including 7// without limitation the rights to use, copy, modify, merge, publish, 8// distribute, sublicense, and/or sell copies of the Software, and to permit 9// persons to whom the Software is furnished to do so, subject to the 10// following conditions: 11// 12// The above copyright notice and this permission notice shall be included 13// in all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 18// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21// USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23'use strict'; 24const common = require('../common'); 25const fixtures = require('../common/fixtures'); 26const tmpdir = require('../common/tmpdir'); 27const assert = require('assert'); 28const fs = require('fs'); 29const path = require('path'); 30 31tmpdir.refresh(); 32 33 34const nonexistentFile = path.join(tmpdir.path, 'non-existent'); 35const nonexistentDir = path.join(tmpdir.path, 'non-existent', 'foo', 'bar'); 36const existingFile = path.join(tmpdir.path, 'existingFile.js'); 37const existingFile2 = path.join(tmpdir.path, 'existingFile2.js'); 38const existingDir = path.join(tmpdir.path, 'dir'); 39const existingDir2 = fixtures.path('keys'); 40fs.mkdirSync(existingDir); 41fs.writeFileSync(existingFile, 'test', 'utf-8'); 42fs.writeFileSync(existingFile2, 'test', 'utf-8'); 43 44 45const { COPYFILE_EXCL } = fs.constants; 46const { internalBinding } = require('internal/test/binding'); 47const { 48 UV_EBADF, 49 UV_EEXIST, 50 UV_EINVAL, 51 UV_ENOENT, 52 UV_ENOTDIR, 53 UV_ENOTEMPTY, 54 UV_EPERM 55} = internalBinding('uv'); 56 57// Template tag function for escaping special characters in strings so that: 58// new RegExp(re`${str}`).test(str) === true 59function re(literals, ...values) { 60 const escapeRE = /[\\^$.*+?()[\]{}|=!<>:-]/g; 61 let result = literals[0].replace(escapeRE, '\\$&'); 62 for (const [i, value] of values.entries()) { 63 result += value.replace(escapeRE, '\\$&'); 64 result += literals[i + 1].replace(escapeRE, '\\$&'); 65 } 66 return result; 67} 68 69// stat 70{ 71 const validateError = (err) => { 72 assert.strictEqual(nonexistentFile, err.path); 73 assert.strictEqual( 74 err.message, 75 `ENOENT: no such file or directory, stat '${nonexistentFile}'`); 76 assert.strictEqual(err.errno, UV_ENOENT); 77 assert.strictEqual(err.code, 'ENOENT'); 78 assert.strictEqual(err.syscall, 'stat'); 79 return true; 80 }; 81 82 fs.stat(nonexistentFile, common.mustCall(validateError)); 83 84 assert.throws( 85 () => fs.statSync(nonexistentFile), 86 validateError 87 ); 88} 89 90// lstat 91{ 92 const validateError = (err) => { 93 assert.strictEqual(nonexistentFile, err.path); 94 assert.strictEqual( 95 err.message, 96 `ENOENT: no such file or directory, lstat '${nonexistentFile}'`); 97 assert.strictEqual(err.errno, UV_ENOENT); 98 assert.strictEqual(err.code, 'ENOENT'); 99 assert.strictEqual(err.syscall, 'lstat'); 100 return true; 101 }; 102 103 fs.lstat(nonexistentFile, common.mustCall(validateError)); 104 assert.throws( 105 () => fs.lstatSync(nonexistentFile), 106 validateError 107 ); 108} 109 110// fstat 111{ 112 const validateError = (err) => { 113 assert.strictEqual(err.message, 'EBADF: bad file descriptor, fstat'); 114 assert.strictEqual(err.errno, UV_EBADF); 115 assert.strictEqual(err.code, 'EBADF'); 116 assert.strictEqual(err.syscall, 'fstat'); 117 return true; 118 }; 119 120 common.runWithInvalidFD((fd) => { 121 fs.fstat(fd, common.mustCall(validateError)); 122 123 assert.throws( 124 () => fs.fstatSync(fd), 125 validateError 126 ); 127 }); 128} 129 130// realpath 131{ 132 const validateError = (err) => { 133 assert.strictEqual(nonexistentFile, err.path); 134 assert.strictEqual( 135 err.message, 136 `ENOENT: no such file or directory, lstat '${nonexistentFile}'`); 137 assert.strictEqual(err.errno, UV_ENOENT); 138 assert.strictEqual(err.code, 'ENOENT'); 139 assert.strictEqual(err.syscall, 'lstat'); 140 return true; 141 }; 142 143 fs.realpath(nonexistentFile, common.mustCall(validateError)); 144 145 assert.throws( 146 () => fs.realpathSync(nonexistentFile), 147 validateError 148 ); 149} 150 151// native realpath 152{ 153 const validateError = (err) => { 154 assert.strictEqual(nonexistentFile, err.path); 155 assert.strictEqual( 156 err.message, 157 `ENOENT: no such file or directory, realpath '${nonexistentFile}'`); 158 assert.strictEqual(err.errno, UV_ENOENT); 159 assert.strictEqual(err.code, 'ENOENT'); 160 assert.strictEqual(err.syscall, 'realpath'); 161 return true; 162 }; 163 164 fs.realpath.native(nonexistentFile, common.mustCall(validateError)); 165 166 assert.throws( 167 () => fs.realpathSync.native(nonexistentFile), 168 validateError 169 ); 170} 171 172// readlink 173{ 174 const validateError = (err) => { 175 assert.strictEqual(nonexistentFile, err.path); 176 assert.strictEqual( 177 err.message, 178 `ENOENT: no such file or directory, readlink '${nonexistentFile}'`); 179 assert.strictEqual(err.errno, UV_ENOENT); 180 assert.strictEqual(err.code, 'ENOENT'); 181 assert.strictEqual(err.syscall, 'readlink'); 182 return true; 183 }; 184 185 fs.readlink(nonexistentFile, common.mustCall(validateError)); 186 187 assert.throws( 188 () => fs.readlinkSync(nonexistentFile), 189 validateError 190 ); 191} 192 193// Link nonexistent file 194{ 195 const validateError = (err) => { 196 assert.strictEqual(nonexistentFile, err.path); 197 // Could be resolved to an absolute path 198 assert.ok(err.dest.endsWith('foo'), 199 `expect ${err.dest} to end with 'foo'`); 200 const regexp = new RegExp('^ENOENT: no such file or directory, link ' + 201 re`'${nonexistentFile}' -> ` + '\'.*foo\''); 202 assert.ok(regexp.test(err.message), 203 `Expect ${err.message} to match ${regexp}`); 204 assert.strictEqual(err.errno, UV_ENOENT); 205 assert.strictEqual(err.code, 'ENOENT'); 206 assert.strictEqual(err.syscall, 'link'); 207 return true; 208 }; 209 210 fs.link(nonexistentFile, 'foo', common.mustCall(validateError)); 211 212 assert.throws( 213 () => fs.linkSync(nonexistentFile, 'foo'), 214 validateError 215 ); 216} 217 218// link existing file 219{ 220 const validateError = (err) => { 221 assert.strictEqual(existingFile, err.path); 222 assert.strictEqual(existingFile2, err.dest); 223 assert.strictEqual( 224 err.message, 225 `EEXIST: file already exists, link '${existingFile}' -> ` + 226 `'${existingFile2}'`); 227 assert.strictEqual(err.errno, UV_EEXIST); 228 assert.strictEqual(err.code, 'EEXIST'); 229 assert.strictEqual(err.syscall, 'link'); 230 return true; 231 }; 232 233 fs.link(existingFile, existingFile2, common.mustCall(validateError)); 234 235 assert.throws( 236 () => fs.linkSync(existingFile, existingFile2), 237 validateError 238 ); 239} 240 241// symlink 242{ 243 const validateError = (err) => { 244 assert.strictEqual(existingFile, err.path); 245 assert.strictEqual(existingFile2, err.dest); 246 assert.strictEqual( 247 err.message, 248 `EEXIST: file already exists, symlink '${existingFile}' -> ` + 249 `'${existingFile2}'`); 250 assert.strictEqual(err.errno, UV_EEXIST); 251 assert.strictEqual(err.code, 'EEXIST'); 252 assert.strictEqual(err.syscall, 'symlink'); 253 return true; 254 }; 255 256 fs.symlink(existingFile, existingFile2, common.mustCall(validateError)); 257 258 assert.throws( 259 () => fs.symlinkSync(existingFile, existingFile2), 260 validateError 261 ); 262} 263 264// unlink 265{ 266 const validateError = (err) => { 267 assert.strictEqual(nonexistentFile, err.path); 268 assert.strictEqual( 269 err.message, 270 `ENOENT: no such file or directory, unlink '${nonexistentFile}'`); 271 assert.strictEqual(err.errno, UV_ENOENT); 272 assert.strictEqual(err.code, 'ENOENT'); 273 assert.strictEqual(err.syscall, 'unlink'); 274 return true; 275 }; 276 277 fs.unlink(nonexistentFile, common.mustCall(validateError)); 278 279 assert.throws( 280 () => fs.unlinkSync(nonexistentFile), 281 validateError 282 ); 283} 284 285// rename 286{ 287 const validateError = (err) => { 288 assert.strictEqual(nonexistentFile, err.path); 289 // Could be resolved to an absolute path 290 assert.ok(err.dest.endsWith('foo'), 291 `expect ${err.dest} to end with 'foo'`); 292 const regexp = new RegExp('ENOENT: no such file or directory, rename ' + 293 re`'${nonexistentFile}' -> ` + '\'.*foo\''); 294 assert.ok(regexp.test(err.message), 295 `Expect ${err.message} to match ${regexp}`); 296 assert.strictEqual(err.errno, UV_ENOENT); 297 assert.strictEqual(err.code, 'ENOENT'); 298 assert.strictEqual(err.syscall, 'rename'); 299 return true; 300 }; 301 302 const destFile = path.join(tmpdir.path, 'foo'); 303 fs.rename(nonexistentFile, destFile, common.mustCall(validateError)); 304 305 assert.throws( 306 () => fs.renameSync(nonexistentFile, destFile), 307 validateError 308 ); 309} 310 311// Rename non-empty directory 312{ 313 const validateError = (err) => { 314 assert.strictEqual(existingDir, err.path); 315 assert.strictEqual(existingDir2, err.dest); 316 assert.strictEqual(err.syscall, 'rename'); 317 // Could be ENOTEMPTY, EEXIST, or EPERM, depending on the platform 318 if (err.code === 'ENOTEMPTY') { 319 assert.strictEqual( 320 err.message, 321 `ENOTEMPTY: directory not empty, rename '${existingDir}' -> ` + 322 `'${existingDir2}'`); 323 assert.strictEqual(err.errno, UV_ENOTEMPTY); 324 } else if (err.code === 'EXDEV') { // Not on the same mounted filesystem 325 assert.strictEqual( 326 err.message, 327 `EXDEV: cross-device link not permitted, rename '${existingDir}' -> ` + 328 `'${existingDir2}'`); 329 } else if (err.code === 'EEXIST') { // smartos and aix 330 assert.strictEqual( 331 err.message, 332 `EEXIST: file already exists, rename '${existingDir}' -> ` + 333 `'${existingDir2}'`); 334 assert.strictEqual(err.errno, UV_EEXIST); 335 } else { // windows 336 assert.strictEqual( 337 err.message, 338 `EPERM: operation not permitted, rename '${existingDir}' -> ` + 339 `'${existingDir2}'`); 340 assert.strictEqual(err.errno, UV_EPERM); 341 assert.strictEqual(err.code, 'EPERM'); 342 } 343 return true; 344 }; 345 346 fs.rename(existingDir, existingDir2, common.mustCall(validateError)); 347 348 assert.throws( 349 () => fs.renameSync(existingDir, existingDir2), 350 validateError 351 ); 352} 353 354// rmdir 355{ 356 const validateError = (err) => { 357 assert.strictEqual(nonexistentFile, err.path); 358 assert.strictEqual( 359 err.message, 360 `ENOENT: no such file or directory, rmdir '${nonexistentFile}'`); 361 assert.strictEqual(err.errno, UV_ENOENT); 362 assert.strictEqual(err.code, 'ENOENT'); 363 assert.strictEqual(err.syscall, 'rmdir'); 364 return true; 365 }; 366 367 fs.rmdir(nonexistentFile, common.mustCall(validateError)); 368 369 assert.throws( 370 () => fs.rmdirSync(nonexistentFile), 371 validateError 372 ); 373} 374 375// rmdir a file 376{ 377 const validateError = (err) => { 378 assert.strictEqual(existingFile, err.path); 379 assert.strictEqual(err.syscall, 'rmdir'); 380 if (err.code === 'ENOTDIR') { 381 assert.strictEqual( 382 err.message, 383 `ENOTDIR: not a directory, rmdir '${existingFile}'`); 384 assert.strictEqual(err.errno, UV_ENOTDIR); 385 } else { // windows 386 assert.strictEqual( 387 err.message, 388 `ENOENT: no such file or directory, rmdir '${existingFile}'`); 389 assert.strictEqual(err.errno, UV_ENOENT); 390 assert.strictEqual(err.code, 'ENOENT'); 391 } 392 return true; 393 }; 394 395 fs.rmdir(existingFile, common.mustCall(validateError)); 396 397 assert.throws( 398 () => fs.rmdirSync(existingFile), 399 validateError 400 ); 401} 402 403// mkdir 404{ 405 const validateError = (err) => { 406 assert.strictEqual(existingFile, err.path); 407 assert.strictEqual( 408 err.message, 409 `EEXIST: file already exists, mkdir '${existingFile}'`); 410 assert.strictEqual(err.errno, UV_EEXIST); 411 assert.strictEqual(err.code, 'EEXIST'); 412 assert.strictEqual(err.syscall, 'mkdir'); 413 return true; 414 }; 415 416 fs.mkdir(existingFile, 0o666, common.mustCall(validateError)); 417 418 assert.throws( 419 () => fs.mkdirSync(existingFile, 0o666), 420 validateError 421 ); 422} 423 424// chmod 425{ 426 const validateError = (err) => { 427 assert.strictEqual(nonexistentFile, err.path); 428 assert.strictEqual( 429 err.message, 430 `ENOENT: no such file or directory, chmod '${nonexistentFile}'`); 431 assert.strictEqual(err.errno, UV_ENOENT); 432 assert.strictEqual(err.code, 'ENOENT'); 433 assert.strictEqual(err.syscall, 'chmod'); 434 return true; 435 }; 436 437 fs.chmod(nonexistentFile, 0o666, common.mustCall(validateError)); 438 439 assert.throws( 440 () => fs.chmodSync(nonexistentFile, 0o666), 441 validateError 442 ); 443} 444 445// open 446{ 447 const validateError = (err) => { 448 assert.strictEqual(nonexistentFile, err.path); 449 assert.strictEqual( 450 err.message, 451 `ENOENT: no such file or directory, open '${nonexistentFile}'`); 452 assert.strictEqual(err.errno, UV_ENOENT); 453 assert.strictEqual(err.code, 'ENOENT'); 454 assert.strictEqual(err.syscall, 'open'); 455 return true; 456 }; 457 458 fs.open(nonexistentFile, 'r', 0o666, common.mustCall(validateError)); 459 460 assert.throws( 461 () => fs.openSync(nonexistentFile, 'r', 0o666), 462 validateError 463 ); 464} 465 466 467// close 468{ 469 const validateError = (err) => { 470 assert.strictEqual(err.message, 'EBADF: bad file descriptor, close'); 471 assert.strictEqual(err.errno, UV_EBADF); 472 assert.strictEqual(err.code, 'EBADF'); 473 assert.strictEqual(err.syscall, 'close'); 474 return true; 475 }; 476 477 common.runWithInvalidFD((fd) => { 478 fs.close(fd, common.mustCall(validateError)); 479 480 assert.throws( 481 () => fs.closeSync(fd), 482 validateError 483 ); 484 }); 485} 486 487// readFile 488{ 489 const validateError = (err) => { 490 assert.strictEqual(nonexistentFile, err.path); 491 assert.strictEqual( 492 err.message, 493 `ENOENT: no such file or directory, open '${nonexistentFile}'`); 494 assert.strictEqual(err.errno, UV_ENOENT); 495 assert.strictEqual(err.code, 'ENOENT'); 496 assert.strictEqual(err.syscall, 'open'); 497 return true; 498 }; 499 500 fs.readFile(nonexistentFile, common.mustCall(validateError)); 501 502 assert.throws( 503 () => fs.readFileSync(nonexistentFile), 504 validateError 505 ); 506} 507 508// readdir 509{ 510 const validateError = (err) => { 511 assert.strictEqual(nonexistentFile, err.path); 512 assert.strictEqual( 513 err.message, 514 `ENOENT: no such file or directory, scandir '${nonexistentFile}'`); 515 assert.strictEqual(err.errno, UV_ENOENT); 516 assert.strictEqual(err.code, 'ENOENT'); 517 assert.strictEqual(err.syscall, 'scandir'); 518 return true; 519 }; 520 521 fs.readdir(nonexistentFile, common.mustCall(validateError)); 522 523 assert.throws( 524 () => fs.readdirSync(nonexistentFile), 525 validateError 526 ); 527} 528 529// ftruncate 530{ 531 const validateError = (err) => { 532 assert.strictEqual(err.syscall, 'ftruncate'); 533 // Could be EBADF or EINVAL, depending on the platform 534 if (err.code === 'EBADF') { 535 assert.strictEqual(err.message, 'EBADF: bad file descriptor, ftruncate'); 536 assert.strictEqual(err.errno, UV_EBADF); 537 } else { 538 assert.strictEqual(err.message, 'EINVAL: invalid argument, ftruncate'); 539 assert.strictEqual(err.errno, UV_EINVAL); 540 assert.strictEqual(err.code, 'EINVAL'); 541 } 542 return true; 543 }; 544 545 common.runWithInvalidFD((fd) => { 546 fs.ftruncate(fd, 4, common.mustCall(validateError)); 547 548 assert.throws( 549 () => fs.ftruncateSync(fd, 4), 550 validateError 551 ); 552 }); 553} 554 555// fdatasync 556{ 557 const validateError = (err) => { 558 assert.strictEqual(err.message, 'EBADF: bad file descriptor, fdatasync'); 559 assert.strictEqual(err.errno, UV_EBADF); 560 assert.strictEqual(err.code, 'EBADF'); 561 assert.strictEqual(err.syscall, 'fdatasync'); 562 return true; 563 }; 564 565 common.runWithInvalidFD((fd) => { 566 fs.fdatasync(fd, common.mustCall(validateError)); 567 568 assert.throws( 569 () => fs.fdatasyncSync(fd), 570 validateError 571 ); 572 }); 573} 574 575// fsync 576{ 577 const validateError = (err) => { 578 assert.strictEqual(err.message, 'EBADF: bad file descriptor, fsync'); 579 assert.strictEqual(err.errno, UV_EBADF); 580 assert.strictEqual(err.code, 'EBADF'); 581 assert.strictEqual(err.syscall, 'fsync'); 582 return true; 583 }; 584 585 common.runWithInvalidFD((fd) => { 586 fs.fsync(fd, common.mustCall(validateError)); 587 588 assert.throws( 589 () => fs.fsyncSync(fd), 590 validateError 591 ); 592 }); 593} 594 595// chown 596if (!common.isWindows) { 597 const validateError = (err) => { 598 assert.strictEqual(nonexistentFile, err.path); 599 assert.strictEqual( 600 err.message, 601 `ENOENT: no such file or directory, chown '${nonexistentFile}'`); 602 assert.strictEqual(err.errno, UV_ENOENT); 603 assert.strictEqual(err.code, 'ENOENT'); 604 assert.strictEqual(err.syscall, 'chown'); 605 return true; 606 }; 607 608 fs.chown(nonexistentFile, process.getuid(), process.getgid(), 609 common.mustCall(validateError)); 610 611 assert.throws( 612 () => fs.chownSync(nonexistentFile, 613 process.getuid(), process.getgid()), 614 validateError 615 ); 616} 617 618// utimes 619if (!common.isAIX) { 620 const validateError = (err) => { 621 assert.strictEqual(nonexistentFile, err.path); 622 assert.strictEqual( 623 err.message, 624 `ENOENT: no such file or directory, utime '${nonexistentFile}'`); 625 assert.strictEqual(err.errno, UV_ENOENT); 626 assert.strictEqual(err.code, 'ENOENT'); 627 assert.strictEqual(err.syscall, 'utime'); 628 return true; 629 }; 630 631 fs.utimes(nonexistentFile, new Date(), new Date(), 632 common.mustCall(validateError)); 633 634 assert.throws( 635 () => fs.utimesSync(nonexistentFile, new Date(), new Date()), 636 validateError 637 ); 638} 639 640// mkdtemp 641{ 642 const validateError = (err) => { 643 const pathPrefix = new RegExp('^' + re`${nonexistentDir}`); 644 assert(pathPrefix.test(err.path), 645 `Expect ${err.path} to match ${pathPrefix}`); 646 647 const prefix = new RegExp('^ENOENT: no such file or directory, mkdtemp ' + 648 re`'${nonexistentDir}`); 649 assert(prefix.test(err.message), 650 `Expect ${err.message} to match ${prefix}`); 651 652 assert.strictEqual(err.errno, UV_ENOENT); 653 assert.strictEqual(err.code, 'ENOENT'); 654 assert.strictEqual(err.syscall, 'mkdtemp'); 655 return true; 656 }; 657 658 fs.mkdtemp(nonexistentDir, common.mustCall(validateError)); 659 660 assert.throws( 661 () => fs.mkdtempSync(nonexistentDir), 662 validateError 663 ); 664} 665 666// Check copyFile with invalid flags. 667{ 668 const validateError = { 669 // TODO: Make sure the error message always also contains the src. 670 message: `EINVAL: invalid argument, copyfile -> '${nonexistentFile}'`, 671 errno: UV_EINVAL, 672 code: 'EINVAL', 673 syscall: 'copyfile' 674 }; 675 676 fs.copyFile(existingFile, nonexistentFile, -1, 677 common.expectsError(validateError)); 678 679 validateError.message = 'EINVAL: invalid argument, copyfile ' + 680 `'${existingFile}' -> '${nonexistentFile}'`; 681 assert.throws( 682 () => fs.copyFileSync(existingFile, nonexistentFile, -1), 683 validateError 684 ); 685} 686 687// copyFile: destination exists but the COPYFILE_EXCL flag is provided. 688{ 689 const validateError = (err) => { 690 if (err.code === 'ENOENT') { // Could be ENOENT or EEXIST 691 assert.strictEqual(err.message, 692 'ENOENT: no such file or directory, copyfile ' + 693 `'${existingFile}' -> '${existingFile2}'`); 694 assert.strictEqual(err.errno, UV_ENOENT); 695 assert.strictEqual(err.code, 'ENOENT'); 696 assert.strictEqual(err.syscall, 'copyfile'); 697 } else { 698 assert.strictEqual(err.message, 699 'EEXIST: file already exists, copyfile ' + 700 `'${existingFile}' -> '${existingFile2}'`); 701 assert.strictEqual(err.errno, UV_EEXIST); 702 assert.strictEqual(err.code, 'EEXIST'); 703 assert.strictEqual(err.syscall, 'copyfile'); 704 } 705 return true; 706 }; 707 708 fs.copyFile(existingFile, existingFile2, COPYFILE_EXCL, 709 common.mustCall(validateError)); 710 711 assert.throws( 712 () => fs.copyFileSync(existingFile, existingFile2, COPYFILE_EXCL), 713 validateError 714 ); 715} 716 717// copyFile: the source does not exist. 718{ 719 const validateError = (err) => { 720 assert.strictEqual(err.message, 721 'ENOENT: no such file or directory, copyfile ' + 722 `'${nonexistentFile}' -> '${existingFile2}'`); 723 assert.strictEqual(err.errno, UV_ENOENT); 724 assert.strictEqual(err.code, 'ENOENT'); 725 assert.strictEqual(err.syscall, 'copyfile'); 726 return true; 727 }; 728 729 fs.copyFile(nonexistentFile, existingFile2, COPYFILE_EXCL, 730 common.mustCall(validateError)); 731 732 assert.throws( 733 () => fs.copyFileSync(nonexistentFile, existingFile2, COPYFILE_EXCL), 734 validateError 735 ); 736} 737 738// read 739{ 740 const validateError = (err) => { 741 assert.strictEqual(err.message, 'EBADF: bad file descriptor, read'); 742 assert.strictEqual(err.errno, UV_EBADF); 743 assert.strictEqual(err.code, 'EBADF'); 744 assert.strictEqual(err.syscall, 'read'); 745 return true; 746 }; 747 748 common.runWithInvalidFD((fd) => { 749 const buf = Buffer.alloc(5); 750 fs.read(fd, buf, 0, 1, 1, common.mustCall(validateError)); 751 752 assert.throws( 753 () => fs.readSync(fd, buf, 0, 1, 1), 754 validateError 755 ); 756 }); 757} 758 759// fchmod 760{ 761 const validateError = (err) => { 762 assert.strictEqual(err.message, 'EBADF: bad file descriptor, fchmod'); 763 assert.strictEqual(err.errno, UV_EBADF); 764 assert.strictEqual(err.code, 'EBADF'); 765 assert.strictEqual(err.syscall, 'fchmod'); 766 return true; 767 }; 768 769 common.runWithInvalidFD((fd) => { 770 fs.fchmod(fd, 0o666, common.mustCall(validateError)); 771 772 assert.throws( 773 () => fs.fchmodSync(fd, 0o666), 774 validateError 775 ); 776 }); 777} 778 779// fchown 780if (!common.isWindows) { 781 const validateError = (err) => { 782 assert.strictEqual(err.message, 'EBADF: bad file descriptor, fchown'); 783 assert.strictEqual(err.errno, UV_EBADF); 784 assert.strictEqual(err.code, 'EBADF'); 785 assert.strictEqual(err.syscall, 'fchown'); 786 return true; 787 }; 788 789 common.runWithInvalidFD((fd) => { 790 fs.fchown(fd, process.getuid(), process.getgid(), 791 common.mustCall(validateError)); 792 793 assert.throws( 794 () => fs.fchownSync(fd, process.getuid(), process.getgid()), 795 validateError 796 ); 797 }); 798} 799 800// write buffer 801{ 802 const validateError = (err) => { 803 assert.strictEqual(err.message, 'EBADF: bad file descriptor, write'); 804 assert.strictEqual(err.errno, UV_EBADF); 805 assert.strictEqual(err.code, 'EBADF'); 806 assert.strictEqual(err.syscall, 'write'); 807 return true; 808 }; 809 810 common.runWithInvalidFD((fd) => { 811 const buf = Buffer.alloc(5); 812 fs.write(fd, buf, 0, 1, 1, common.mustCall(validateError)); 813 814 assert.throws( 815 () => fs.writeSync(fd, buf, 0, 1, 1), 816 validateError 817 ); 818 }); 819} 820 821// write string 822{ 823 const validateError = (err) => { 824 assert.strictEqual(err.message, 'EBADF: bad file descriptor, write'); 825 assert.strictEqual(err.errno, UV_EBADF); 826 assert.strictEqual(err.code, 'EBADF'); 827 assert.strictEqual(err.syscall, 'write'); 828 return true; 829 }; 830 831 common.runWithInvalidFD((fd) => { 832 fs.write(fd, 'test', 1, common.mustCall(validateError)); 833 834 assert.throws( 835 () => fs.writeSync(fd, 'test', 1), 836 validateError 837 ); 838 }); 839} 840 841 842// futimes 843if (!common.isAIX) { 844 const validateError = (err) => { 845 assert.strictEqual(err.message, 'EBADF: bad file descriptor, futime'); 846 assert.strictEqual(err.errno, UV_EBADF); 847 assert.strictEqual(err.code, 'EBADF'); 848 assert.strictEqual(err.syscall, 'futime'); 849 return true; 850 }; 851 852 common.runWithInvalidFD((fd) => { 853 fs.futimes(fd, new Date(), new Date(), common.mustCall(validateError)); 854 855 assert.throws( 856 () => fs.futimesSync(fd, new Date(), new Date()), 857 validateError 858 ); 859 }); 860} 861