| OLD | NEW |
| 1 /////////////////////////////////////////////////////////////////////////////// | 1 /////////////////////////////////////////////////////////////////////////////// |
| 2 // | 2 // |
| 3 /// \file file_io.c | 3 /// \file file_io.c |
| 4 /// \brief File opening, unlinking, and closing | 4 /// \brief File opening, unlinking, and closing |
| 5 // | 5 // |
| 6 // Author: Lasse Collin | 6 // Author: Lasse Collin |
| 7 // | 7 // |
| 8 // This file has been put into the public domain. | 8 // This file has been put into the public domain. |
| 9 // You can do whatever you want with this file. | 9 // You can do whatever you want with this file. |
| 10 // | 10 // |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 static int stdout_flags = 0; | 46 static int stdout_flags = 0; |
| 47 #endif | 47 #endif |
| 48 | 48 |
| 49 | 49 |
| 50 static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size); | 50 static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size); |
| 51 | 51 |
| 52 | 52 |
| 53 extern void | 53 extern void |
| 54 io_init(void) | 54 io_init(void) |
| 55 { | 55 { |
| 56 » // Make sure that stdin, stdout, and and stderr are connected to | 56 » // Make sure that stdin, stdout, and stderr are connected to |
| 57 // a valid file descriptor. Exit immediately with exit code ERROR | 57 // a valid file descriptor. Exit immediately with exit code ERROR |
| 58 // if we cannot make the file descriptors valid. Maybe we should | 58 // if we cannot make the file descriptors valid. Maybe we should |
| 59 // print an error message, but our stderr could be screwed anyway. | 59 // print an error message, but our stderr could be screwed anyway. |
| 60 tuklib_open_stdxxx(E_ERROR); | 60 tuklib_open_stdxxx(E_ERROR); |
| 61 | 61 |
| 62 #ifndef TUKLIB_DOSLIKE | 62 #ifndef TUKLIB_DOSLIKE |
| 63 // If fchown() fails setting the owner, we warn about it only if | 63 // If fchown() fails setting the owner, we warn about it only if |
| 64 // we are root. | 64 // we are root. |
| 65 warn_fchown = geteuid() == 0; | 65 warn_fchown = geteuid() == 0; |
| 66 #endif | 66 #endif |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 if (pair->src_fd == -1) { | 363 if (pair->src_fd == -1) { |
| 364 // If we were interrupted, don't display any error message. | 364 // If we were interrupted, don't display any error message. |
| 365 if (errno == EINTR) { | 365 if (errno == EINTR) { |
| 366 // All the signals that don't have SA_RESTART | 366 // All the signals that don't have SA_RESTART |
| 367 // set user_abort. | 367 // set user_abort. |
| 368 assert(user_abort); | 368 assert(user_abort); |
| 369 return true; | 369 return true; |
| 370 } | 370 } |
| 371 | 371 |
| 372 #ifdef O_NOFOLLOW | 372 #ifdef O_NOFOLLOW |
| 373 » » // Give an understandable error message in if reason | 373 » » // Give an understandable error message if the reason |
| 374 // for failing was that the file was a symbolic link. | 374 // for failing was that the file was a symbolic link. |
| 375 // | 375 // |
| 376 // Note that at least Linux, OpenBSD, Solaris, and Darwin | 376 // Note that at least Linux, OpenBSD, Solaris, and Darwin |
| 377 » » // use ELOOP to indicate if O_NOFOLLOW was the reason | 377 » » // use ELOOP to indicate that O_NOFOLLOW was the reason |
| 378 // that open() failed. Because there may be | 378 // that open() failed. Because there may be |
| 379 // directories in the pathname, ELOOP may occur also | 379 // directories in the pathname, ELOOP may occur also |
| 380 // because of a symlink loop in the directory part. | 380 // because of a symlink loop in the directory part. |
| 381 » » // So ELOOP doesn't tell us what actually went wrong. | 381 » » // So ELOOP doesn't tell us what actually went wrong, |
| 382 » » // and this stupidity went into POSIX-1.2008 too. |
| 382 // | 383 // |
| 383 // FreeBSD associates EMLINK with O_NOFOLLOW and | 384 // FreeBSD associates EMLINK with O_NOFOLLOW and |
| 384 // Tru64 uses ENOTSUP. We use these directly here | 385 // Tru64 uses ENOTSUP. We use these directly here |
| 385 // and skip the lstat() call and the associated race. | 386 // and skip the lstat() call and the associated race. |
| 386 // I want to hear if there are other kernels that | 387 // I want to hear if there are other kernels that |
| 387 // fail with something else than ELOOP with O_NOFOLLOW. | 388 // fail with something else than ELOOP with O_NOFOLLOW. |
| 388 bool was_symlink = false; | 389 bool was_symlink = false; |
| 389 | 390 |
| 390 # if defined(__FreeBSD__) || defined(__DragonFly__) | 391 # if defined(__FreeBSD__) || defined(__DragonFly__) |
| 391 if (errno == EMLINK) | 392 if (errno == EMLINK) |
| 392 was_symlink = true; | 393 was_symlink = true; |
| 393 | 394 |
| 394 # elif defined(__digital__) && defined(__unix__) | 395 # elif defined(__digital__) && defined(__unix__) |
| 395 if (errno == ENOTSUP) | 396 if (errno == ENOTSUP) |
| 396 was_symlink = true; | 397 was_symlink = true; |
| 397 | 398 |
| 398 # elif defined(__NetBSD__) | 399 # elif defined(__NetBSD__) |
| 399 » » // FIXME? As of 2008-11-20, NetBSD doesn't document what | 400 » » // As of 2010-09-05, NetBSD doesn't document what errno is |
| 400 » » // errno is used with O_NOFOLLOW. It seems to be EFTYPE, | 401 » » // used with O_NOFOLLOW. It is EFTYPE though, and I |
| 401 » » // but since it isn't documented, it may be wrong to rely | 402 » » // understood that is very unlikely to change even though |
| 402 » » // on it here. | 403 » » // it is undocumented. |
| 403 if (errno == EFTYPE) | 404 if (errno == EFTYPE) |
| 404 was_symlink = true; | 405 was_symlink = true; |
| 405 | 406 |
| 406 # else | 407 # else |
| 407 if (errno == ELOOP && !follow_symlinks) { | 408 if (errno == ELOOP && !follow_symlinks) { |
| 408 const int saved_errno = errno; | 409 const int saved_errno = errno; |
| 409 struct stat st; | 410 struct stat st; |
| 410 if (lstat(pair->src_name, &st) == 0 | 411 if (lstat(pair->src_name, &st) == 0 |
| 411 && S_ISLNK(st.st_mode)) | 412 && S_ISLNK(st.st_mode)) |
| 412 was_symlink = true; | 413 was_symlink = true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 // the permissions, and when unlinking. | 450 // the permissions, and when unlinking. |
| 450 if (fstat(pair->src_fd, &pair->src_st)) | 451 if (fstat(pair->src_fd, &pair->src_st)) |
| 451 goto error_msg; | 452 goto error_msg; |
| 452 | 453 |
| 453 if (S_ISDIR(pair->src_st.st_mode)) { | 454 if (S_ISDIR(pair->src_st.st_mode)) { |
| 454 message_warning(_("%s: Is a directory, skipping"), | 455 message_warning(_("%s: Is a directory, skipping"), |
| 455 pair->src_name); | 456 pair->src_name); |
| 456 goto error; | 457 goto error; |
| 457 } | 458 } |
| 458 | 459 |
| 459 » if (reg_files_only) { | 460 » if (reg_files_only && !S_ISREG(pair->src_st.st_mode)) { |
| 460 » » if (!S_ISREG(pair->src_st.st_mode)) { | 461 » » message_warning(_("%s: Not a regular file, skipping"), |
| 461 » » » message_warning(_("%s: Not a regular file, " | 462 » » » » pair->src_name); |
| 462 » » » » » "skipping"), pair->src_name); | 463 » » goto error; |
| 463 » » » goto error; | 464 » } |
| 464 » » } | |
| 465 | 465 |
| 466 // These are meaningless on Windows. | |
| 467 #ifndef TUKLIB_DOSLIKE | 466 #ifndef TUKLIB_DOSLIKE |
| 467 if (reg_files_only && !opt_force) { |
| 468 if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) { | 468 if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) { |
| 469 // gzip rejects setuid and setgid files even | 469 // gzip rejects setuid and setgid files even |
| 470 // when --force was used. bzip2 doesn't check | 470 // when --force was used. bzip2 doesn't check |
| 471 // for them, but calls fchown() after fchmod(), | 471 // for them, but calls fchown() after fchmod(), |
| 472 // and many systems automatically drop setuid | 472 // and many systems automatically drop setuid |
| 473 // and setgid bits there. | 473 // and setgid bits there. |
| 474 // | 474 // |
| 475 // We accept setuid and setgid files if | 475 // We accept setuid and setgid files if |
| 476 // --force was used. We drop these bits | 476 // --force was used. We drop these bits |
| 477 // explicitly in io_copy_attr(). | 477 // explicitly in io_copy_attr(). |
| 478 message_warning(_("%s: File has setuid or " | 478 message_warning(_("%s: File has setuid or " |
| 479 "setgid bit set, skipping"), | 479 "setgid bit set, skipping"), |
| 480 pair->src_name); | 480 pair->src_name); |
| 481 goto error; | 481 goto error; |
| 482 } | 482 } |
| 483 | 483 |
| 484 if (pair->src_st.st_mode & S_ISVTX) { | 484 if (pair->src_st.st_mode & S_ISVTX) { |
| 485 message_warning(_("%s: File has sticky bit " | 485 message_warning(_("%s: File has sticky bit " |
| 486 "set, skipping"), | 486 "set, skipping"), |
| 487 pair->src_name); | 487 pair->src_name); |
| 488 goto error; | 488 goto error; |
| 489 } | 489 } |
| 490 | 490 |
| 491 if (pair->src_st.st_nlink > 1) { | 491 if (pair->src_st.st_nlink > 1) { |
| 492 message_warning(_("%s: Input file has more " | 492 message_warning(_("%s: Input file has more " |
| 493 "than one hard link, " | 493 "than one hard link, " |
| 494 "skipping"), pair->src_name); | 494 "skipping"), pair->src_name); |
| 495 goto error; | 495 goto error; |
| 496 } | 496 } |
| 497 } |
| 497 #endif | 498 #endif |
| 498 } | |
| 499 | 499 |
| 500 return false; | 500 return false; |
| 501 | 501 |
| 502 error_msg: | 502 error_msg: |
| 503 message_error("%s: %s", pair->src_name, strerror(errno)); | 503 message_error("%s: %s", pair->src_name, strerror(errno)); |
| 504 error: | 504 error: |
| 505 (void)close(pair->src_fd); | 505 (void)close(pair->src_fd); |
| 506 return true; | 506 return true; |
| 507 } | 507 } |
| 508 | 508 |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 strerror(errno)); | 948 strerror(errno)); |
| 949 return true; | 949 return true; |
| 950 } | 950 } |
| 951 | 951 |
| 952 pair->dest_pending_sparse = 0; | 952 pair->dest_pending_sparse = 0; |
| 953 } | 953 } |
| 954 } | 954 } |
| 955 | 955 |
| 956 return io_write_buf(pair, buf->u8, size); | 956 return io_write_buf(pair, buf->u8, size); |
| 957 } | 957 } |
| OLD | NEW |