]> icculus.org git repositories - icculus/xz.git/blob - src/xz/file_io.c
Remove --force from xzdec.
[icculus/xz.git] / src / xz / file_io.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       file_io.c
4 /// \brief      File opening, unlinking, and closing
5 //
6 //  Author:     Lasse Collin
7 //
8 //  This file has been put into the public domain.
9 //  You can do whatever you want with this file.
10 //
11 ///////////////////////////////////////////////////////////////////////////////
12
13 #include "private.h"
14
15 #include <fcntl.h>
16
17 #ifdef DOSLIKE
18 #       include <io.h>
19 #endif
20
21 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
22 #       include <sys/time.h>
23 #elif defined(HAVE_UTIME)
24 #       include <utime.h>
25 #endif
26
27 #ifndef O_BINARY
28 #       define O_BINARY 0
29 #endif
30
31 #ifndef O_NOCTTY
32 #       define O_NOCTTY 0
33 #endif
34
35 #ifndef DOSLIKE
36 #       include "open_stdxxx.h"
37 static bool warn_fchown;
38 #endif
39
40
41 extern void
42 io_init(void)
43 {
44 #ifndef DOSLIKE
45         // Make sure that stdin, stdout, and and stderr are connected to
46         // a valid file descriptor. Exit immediatelly with exit code ERROR
47         // if we cannot make the file descriptors valid. Maybe we should
48         // print an error message, but our stderr could be screwed anyway.
49         open_stdxxx(E_ERROR);
50
51         // If fchown() fails setting the owner, we warn about it only if
52         // we are root.
53         warn_fchown = geteuid() == 0;
54 #endif
55
56 #ifdef __DJGPP__
57         // Avoid doing useless things when statting files.
58         // This isn't important but doesn't hurt.
59         _djstat_flags = _STAT_INODE | _STAT_EXEC_EXT
60                         | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
61 #endif
62
63         return;
64 }
65
66
67 /// \brief      Unlinks a file
68 ///
69 /// This tries to verify that the file being unlinked really is the file that
70 /// we want to unlink by verifying device and inode numbers. There's still
71 /// a small unavoidable race, but this is much better than nothing (the file
72 /// could have been moved/replaced even hours earlier).
73 static void
74 io_unlink(const char *name, const struct stat *known_st)
75 {
76 #ifdef DOSLIKE
77         // On Windows, st_ino is meaningless, so don't bother testing it.
78         // Just silence a compiler warning.
79         (void)known_st;
80 #else
81         struct stat new_st;
82
83         if (lstat(name, &new_st)
84                         || new_st.st_dev != known_st->st_dev
85                         || new_st.st_ino != known_st->st_ino)
86                 message_error(_("%s: File seems to be moved, not removing"),
87                                 name);
88         else
89 #endif
90                 // There's a race condition between lstat() and unlink()
91                 // but at least we have tried to avoid removing wrong file.
92                 if (unlink(name))
93                         message_error(_("%s: Cannot remove: %s"),
94                                         name, strerror(errno));
95
96         return;
97 }
98
99
100 /// \brief      Copies owner/group and permissions
101 ///
102 /// \todo       ACL and EA support
103 ///
104 static void
105 io_copy_attrs(const file_pair *pair)
106 {
107         // Skip chown and chmod on Windows.
108 #ifndef DOSLIKE
109         // This function is more tricky than you may think at first.
110         // Blindly copying permissions may permit users to access the
111         // destination file who didn't have permission to access the
112         // source file.
113
114         // Try changing the owner of the file. If we aren't root or the owner
115         // isn't already us, fchown() probably doesn't succeed. We warn
116         // about failing fchown() only if we are root.
117         if (fchown(pair->dest_fd, pair->src_st.st_uid, -1) && warn_fchown)
118                 message_warning(_("%s: Cannot set the file owner: %s"),
119                                 pair->dest_name, strerror(errno));
120
121         mode_t mode;
122
123         if (fchown(pair->dest_fd, -1, pair->src_st.st_gid)) {
124                 message_warning(_("%s: Cannot set the file group: %s"),
125                                 pair->dest_name, strerror(errno));
126                 // We can still safely copy some additional permissions:
127                 // `group' must be at least as strict as `other' and
128                 // also vice versa.
129                 //
130                 // NOTE: After this, the owner of the source file may
131                 // get additional permissions. This shouldn't be too bad,
132                 // because the owner would have had permission to chmod
133                 // the original file anyway.
134                 mode = ((pair->src_st.st_mode & 0070) >> 3)
135                                 & (pair->src_st.st_mode & 0007);
136                 mode = (pair->src_st.st_mode & 0700) | (mode << 3) | mode;
137         } else {
138                 // Drop the setuid, setgid, and sticky bits.
139                 mode = pair->src_st.st_mode & 0777;
140         }
141
142         if (fchmod(pair->dest_fd, mode))
143                 message_warning(_("%s: Cannot set the file permissions: %s"),
144                                 pair->dest_name, strerror(errno));
145 #endif
146
147         // Copy the timestamps. We have several possible ways to do this, of
148         // which some are better in both security and precision.
149         //
150         // First, get the nanosecond part of the timestamps. As of writing,
151         // it's not standardized by POSIX, and there are several names for
152         // the same thing in struct stat.
153         long atime_nsec;
154         long mtime_nsec;
155
156 #       if defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
157         // GNU and Solaris
158         atime_nsec = pair->src_st.st_atim.tv_nsec;
159         mtime_nsec = pair->src_st.st_mtim.tv_nsec;
160
161 #       elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
162         // BSD
163         atime_nsec = pair->src_st.st_atimespec.tv_nsec;
164         mtime_nsec = pair->src_st.st_mtimespec.tv_nsec;
165
166 #       elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
167         // GNU and BSD without extensions
168         atime_nsec = pair->src_st.st_atimensec;
169         mtime_nsec = pair->src_st.st_mtimensec;
170
171 #       elif defined(HAVE_STRUCT_STAT_ST_UATIME)
172         // Tru64
173         atime_nsec = pair->src_st.st_uatime * 1000;
174         mtime_nsec = pair->src_st.st_umtime * 1000;
175
176 #       elif defined(HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC)
177         // UnixWare
178         atime_nsec = pair->src_st.st_atim.st__tim.tv_nsec;
179         mtime_nsec = pair->src_st.st_mtim.st__tim.tv_nsec;
180
181 #       else
182         // Safe fallback
183         atime_nsec = 0;
184         mtime_nsec = 0;
185 #       endif
186
187         // Construct a structure to hold the timestamps and call appropriate
188         // function to set the timestamps.
189 #if defined(HAVE_FUTIMENS)
190         // Use nanosecond precision.
191         struct timespec tv[2];
192         tv[0].tv_sec = pair->src_st.st_atime;
193         tv[0].tv_nsec = atime_nsec;
194         tv[1].tv_sec = pair->src_st.st_mtime;
195         tv[1].tv_nsec = mtime_nsec;
196
197         (void)futimens(pair->dest_fd, tv);
198
199 #elif defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
200         // Use microsecond precision.
201         struct timeval tv[2];
202         tv[0].tv_sec = pair->src_st.st_atime;
203         tv[0].tv_usec = atime_nsec / 1000;
204         tv[1].tv_sec = pair->src_st.st_mtime;
205         tv[1].tv_usec = mtime_nsec / 1000;
206
207 #       if defined(HAVE_FUTIMES)
208         (void)futimes(pair->dest_fd, tv);
209 #       elif defined(HAVE_FUTIMESAT)
210         (void)futimesat(pair->dest_fd, NULL, tv);
211 #       else
212         // Argh, no function to use a file descriptor to set the timestamp.
213         (void)utimes(pair->dest_name, tv);
214 #       endif
215
216 #elif defined(HAVE_UTIME)
217         // Use one-second precision. utime() doesn't support using file
218         // descriptor either. Some systems have broken utime() prototype
219         // so don't make this const.
220         struct utimbuf buf = {
221                 .actime = pair->src_st.st_atime,
222                 .modtime = pair->src_st.st_mtime,
223         };
224
225         // Avoid warnings.
226         (void)atime_nsec;
227         (void)mtime_nsec;
228
229         (void)utime(pair->dest_name, &buf);
230 #endif
231
232         return;
233 }
234
235
236 /// Opens the source file. Returns false on success, true on error.
237 static bool
238 io_open_src(file_pair *pair)
239 {
240         // There's nothing to open when reading from stdin.
241         if (pair->src_name == stdin_filename) {
242                 pair->src_fd = STDIN_FILENO;
243 #ifdef DOSLIKE
244                 setmode(STDIN_FILENO, O_BINARY);
245 #endif
246                 return false;
247         }
248
249         // We accept only regular files if we are writing the output
250         // to disk too, and if --force was not given.
251         const bool reg_files_only = !opt_stdout && !opt_force;
252
253         // Flags for open()
254         int flags = O_RDONLY | O_BINARY | O_NOCTTY;
255
256 #ifndef DOSLIKE
257         // If we accept only regular files, we need to be careful to avoid
258         // problems with special files like devices and FIFOs. O_NONBLOCK
259         // prevents blocking when opening such files. When we want to accept
260         // special files, we must not use O_NONBLOCK, or otherwise we won't
261         // block waiting e.g. FIFOs to become readable.
262         if (reg_files_only)
263                 flags |= O_NONBLOCK;
264 #endif
265
266 #if defined(O_NOFOLLOW)
267         if (reg_files_only)
268                 flags |= O_NOFOLLOW;
269 #elif !defined(DOSLIKE)
270         // Some POSIX-like systems lack O_NOFOLLOW (it's not required
271         // by POSIX). Check for symlinks with a separate lstat() on
272         // these systems.
273         if (reg_files_only) {
274                 struct stat st;
275                 if (lstat(pair->src_name, &st)) {
276                         message_error("%s: %s", pair->src_name,
277                                         strerror(errno));
278                         return true;
279
280                 } else if (S_ISLNK(st.st_mode)) {
281                         message_warning(_("%s: Is a symbolic link, "
282                                         "skipping"), pair->src_name);
283                         return true;
284                 }
285         }
286 #endif
287
288         // Try to open the file. If we are accepting non-regular files,
289         // unblock the caught signals so that open() can be interrupted
290         // if it blocks e.g. due to a FIFO file.
291         if (!reg_files_only)
292                 signals_unblock();
293
294         // Maybe this wouldn't need a loop, since all the signal handlers for
295         // which we don't use SA_RESTART set user_abort to true. But it
296         // doesn't hurt to have it just in case.
297         do {
298                 pair->src_fd = open(pair->src_name, flags);
299         } while (pair->src_fd == -1 && errno == EINTR && !user_abort);
300
301         if (!reg_files_only)
302                 signals_block();
303
304         if (pair->src_fd == -1) {
305                 // If we were interrupted, don't display any error message.
306                 if (errno == EINTR) {
307                         // All the signals that don't have SA_RESTART
308                         // set user_abort.
309                         assert(user_abort);
310                         return true;
311                 }
312
313 #ifdef O_NOFOLLOW
314                 // Give an understandable error message in if reason
315                 // for failing was that the file was a symbolic link.
316                 //
317                 // Note that at least Linux, OpenBSD, Solaris, and Darwin
318                 // use ELOOP to indicate if O_NOFOLLOW was the reason
319                 // that open() failed. Because there may be
320                 // directories in the pathname, ELOOP may occur also
321                 // because of a symlink loop in the directory part.
322                 // So ELOOP doesn't tell us what actually went wrong.
323                 //
324                 // FreeBSD associates EMLINK with O_NOFOLLOW and
325                 // Tru64 uses ENOTSUP. We use these directly here
326                 // and skip the lstat() call and the associated race.
327                 // I want to hear if there are other kernels that
328                 // fail with something else than ELOOP with O_NOFOLLOW.
329                 bool was_symlink = false;
330
331 #       if defined(__FreeBSD__) || defined(__DragonFly__)
332                 if (errno == EMLINK)
333                         was_symlink = true;
334
335 #       elif defined(__digital__) && defined(__unix__)
336                 if (errno == ENOTSUP)
337                         was_symlink = true;
338
339 #       elif defined(__NetBSD__)
340                 // FIXME? As of 2008-11-20, NetBSD doesn't document what
341                 // errno is used with O_NOFOLLOW. It seems to be EFTYPE,
342                 // but since it isn't documented, it may be wrong to rely
343                 // on it here.
344                 if (errno == EFTYPE)
345                         was_symlink = true;
346
347 #       else
348                 if (errno == ELOOP && reg_files_only) {
349                         const int saved_errno = errno;
350                         struct stat st;
351                         if (lstat(pair->src_name, &st) == 0
352                                         && S_ISLNK(st.st_mode))
353                                 was_symlink = true;
354
355                         errno = saved_errno;
356                 }
357 #       endif
358
359                 if (was_symlink)
360                         message_warning(_("%s: Is a symbolic link, "
361                                         "skipping"), pair->src_name);
362                 else
363 #endif
364                         // Something else than O_NOFOLLOW failing
365                         // (assuming that the race conditions didn't
366                         // confuse us).
367                         message_error("%s: %s", pair->src_name,
368                                         strerror(errno));
369
370                 return true;
371         }
372
373 #ifndef DOSLIKE
374         // Drop O_NONBLOCK, which is used only when we are accepting only
375         // regular files. After the open() call, we want things to block
376         // instead of giving EAGAIN.
377         if (reg_files_only) {
378                 flags = fcntl(pair->src_fd, F_GETFL);
379                 if (flags == -1)
380                         goto error_msg;
381
382                 flags &= ~O_NONBLOCK;
383
384                 if (fcntl(pair->src_fd, F_SETFL, flags))
385                         goto error_msg;
386         }
387 #endif
388
389         // Stat the source file. We need the result also when we copy
390         // the permissions, and when unlinking.
391         if (fstat(pair->src_fd, &pair->src_st))
392                 goto error_msg;
393
394         if (S_ISDIR(pair->src_st.st_mode)) {
395                 message_warning(_("%s: Is a directory, skipping"),
396                                 pair->src_name);
397                 goto error;
398         }
399
400         if (reg_files_only) {
401                 if (!S_ISREG(pair->src_st.st_mode)) {
402                         message_warning(_("%s: Not a regular file, "
403                                         "skipping"), pair->src_name);
404                         goto error;
405                 }
406
407                 // These are meaningless on Windows.
408 #ifndef DOSLIKE
409                 if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
410                         // gzip rejects setuid and setgid files even
411                         // when --force was used. bzip2 doesn't check
412                         // for them, but calls fchown() after fchmod(),
413                         // and many systems automatically drop setuid
414                         // and setgid bits there.
415                         //
416                         // We accept setuid and setgid files if
417                         // --force was used. We drop these bits
418                         // explicitly in io_copy_attr().
419                         message_warning(_("%s: File has setuid or "
420                                         "setgid bit set, skipping"),
421                                         pair->src_name);
422                         goto error;
423                 }
424
425                 if (pair->src_st.st_mode & S_ISVTX) {
426                         message_warning(_("%s: File has sticky bit "
427                                         "set, skipping"),
428                                         pair->src_name);
429                         goto error;
430                 }
431
432                 if (pair->src_st.st_nlink > 1) {
433                         message_warning(_("%s: Input file has more "
434                                         "than one hard link, "
435                                         "skipping"), pair->src_name);
436                         goto error;
437                 }
438 #endif
439         }
440
441         return false;
442
443 error_msg:
444         message_error("%s: %s", pair->src_name, strerror(errno));
445 error:
446         (void)close(pair->src_fd);
447         return true;
448 }
449
450
451 /// \brief      Closes source file of the file_pair structure
452 ///
453 /// \param      pair    File whose src_fd should be closed
454 /// \param      success If true, the file will be removed from the disk if
455 ///                     closing succeeds and --keep hasn't been used.
456 static void
457 io_close_src(file_pair *pair, bool success)
458 {
459         if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
460 #ifdef DOSLIKE
461                 (void)close(pair->src_fd);
462 #endif
463
464                 // If we are going to unlink(), do it before closing the file.
465                 // This way there's no risk that someone replaces the file and
466                 // happens to get same inode number, which would make us
467                 // unlink() wrong file.
468                 //
469                 // NOTE: DOS-like systems are an exception to this, because
470                 // they don't allow unlinking files that are open. *sigh*
471                 if (success && !opt_keep_original)
472                         io_unlink(pair->src_name, &pair->src_st);
473
474 #ifndef DOSLIKE
475                 (void)close(pair->src_fd);
476 #endif
477         }
478
479         return;
480 }
481
482
483 static bool
484 io_open_dest(file_pair *pair)
485 {
486         if (opt_stdout || pair->src_fd == STDIN_FILENO) {
487                 // We don't modify or free() this.
488                 pair->dest_name = (char *)"(stdout)";
489                 pair->dest_fd = STDOUT_FILENO;
490 #ifdef DOSLIKE
491                 setmode(STDOUT_FILENO, O_BINARY);
492 #endif
493                 return false;
494         }
495
496         pair->dest_name = suffix_get_dest_name(pair->src_name);
497         if (pair->dest_name == NULL)
498                 return true;
499
500         // If --force was used, unlink the target file first.
501         if (opt_force && unlink(pair->dest_name) && errno != ENOENT) {
502                 message_error("%s: Cannot unlink: %s",
503                                 pair->dest_name, strerror(errno));
504                 free(pair->dest_name);
505                 return true;
506         }
507
508         if (opt_force && unlink(pair->dest_name) && errno != ENOENT) {
509                 message_error("%s: Cannot unlink: %s", pair->dest_name,
510                                 strerror(errno));
511                 free(pair->dest_name);
512                 return true;
513         }
514
515         // Open the file.
516         const int flags = O_WRONLY | O_BINARY | O_NOCTTY | O_CREAT | O_EXCL;
517         const mode_t mode = S_IRUSR | S_IWUSR;
518         pair->dest_fd = open(pair->dest_name, flags, mode);
519
520         if (pair->dest_fd == -1) {
521                 // Don't bother with error message if user requested
522                 // us to exit anyway.
523                 if (!user_abort)
524                         message_error("%s: %s", pair->dest_name,
525                                         strerror(errno));
526
527                 free(pair->dest_name);
528                 return true;
529         }
530
531         // If this really fails... well, we have a safe fallback.
532         if (fstat(pair->dest_fd, &pair->dest_st)) {
533                 pair->dest_st.st_dev = 0;
534                 pair->dest_st.st_ino = 0;
535         }
536
537         return false;
538 }
539
540
541 /// \brief      Closes destination file of the file_pair structure
542 ///
543 /// \param      pair    File whose dest_fd should be closed
544 /// \param      success If false, the file will be removed from the disk.
545 ///
546 /// \return     Zero if closing succeeds. On error, -1 is returned and
547 ///             error message printed.
548 static int
549 io_close_dest(file_pair *pair, bool success)
550 {
551         if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
552                 return 0;
553
554         if (close(pair->dest_fd)) {
555                 message_error(_("%s: Closing the file failed: %s"),
556                                 pair->dest_name, strerror(errno));
557
558                 // Closing destination file failed, so we cannot trust its
559                 // contents. Get rid of junk:
560                 io_unlink(pair->dest_name, &pair->dest_st);
561                 free(pair->dest_name);
562                 return -1;
563         }
564
565         // If the operation using this file wasn't successful, we git rid
566         // of the junk file.
567         if (!success)
568                 io_unlink(pair->dest_name, &pair->dest_st);
569
570         free(pair->dest_name);
571
572         return 0;
573 }
574
575
576 extern file_pair *
577 io_open(const char *src_name)
578 {
579         if (is_empty_filename(src_name))
580                 return NULL;
581
582         // Since we have only one file open at a time, we can use
583         // a statically allocated structure.
584         static file_pair pair;
585
586         pair = (file_pair){
587                 .src_name = src_name,
588                 .dest_name = NULL,
589                 .src_fd = -1,
590                 .dest_fd = -1,
591                 .src_eof = false,
592         };
593
594         // Block the signals, for which we have a custom signal handler, so
595         // that we don't need to worry about EINTR.
596         signals_block();
597
598         file_pair *ret = NULL;
599         if (!io_open_src(&pair)) {
600                 // io_open_src() may have unblocked the signals temporarily,
601                 // and thus user_abort may have got set even if open()
602                 // succeeded.
603                 if (user_abort || io_open_dest(&pair))
604                         io_close_src(&pair, false);
605                 else
606                         ret = &pair;
607         }
608
609         signals_unblock();
610
611         return ret;
612 }
613
614
615 extern void
616 io_close(file_pair *pair, bool success)
617 {
618         signals_block();
619
620         if (success && pair->dest_fd != STDOUT_FILENO)
621                 io_copy_attrs(pair);
622
623         // Close the destination first. If it fails, we must not remove
624         // the source file!
625         if (io_close_dest(pair, success))
626                 success = false;
627
628         // Close the source file, and unlink it if the operation using this
629         // file pair was successful and we haven't requested to keep the
630         // source file.
631         io_close_src(pair, success);
632
633         signals_unblock();
634
635         return;
636 }
637
638
639 extern size_t
640 io_read(file_pair *pair, uint8_t *buf, size_t size)
641 {
642         // We use small buffers here.
643         assert(size < SSIZE_MAX);
644
645         size_t left = size;
646
647         while (left > 0) {
648                 const ssize_t amount = read(pair->src_fd, buf, left);
649
650                 if (amount == 0) {
651                         pair->src_eof = true;
652                         break;
653                 }
654
655                 if (amount == -1) {
656                         if (errno == EINTR) {
657                                 if (user_abort)
658                                         return SIZE_MAX;
659
660                                 continue;
661                         }
662
663                         message_error(_("%s: Read error: %s"),
664                                         pair->src_name, strerror(errno));
665
666                         // FIXME Is this needed?
667                         pair->src_eof = true;
668
669                         return SIZE_MAX;
670                 }
671
672                 buf += (size_t)(amount);
673                 left -= (size_t)(amount);
674         }
675
676         return size - left;
677 }
678
679
680 extern bool
681 io_write(const file_pair *pair, const uint8_t *buf, size_t size)
682 {
683         assert(size < SSIZE_MAX);
684
685         while (size > 0) {
686                 const ssize_t amount = write(pair->dest_fd, buf, size);
687                 if (amount == -1) {
688                         if (errno == EINTR) {
689                                 if (user_abort)
690                                         return -1;
691
692                                 continue;
693                         }
694
695                         // Handle broken pipe specially. gzip and bzip2
696                         // don't print anything on SIGPIPE. In addition,
697                         // gzip --quiet uses exit status 2 (warning) on
698                         // broken pipe instead of whatever raise(SIGPIPE)
699                         // would make it return. It is there to hide "Broken
700                         // pipe" message on some old shells (probably old
701                         // GNU bash).
702                         //
703                         // We don't do anything special with --quiet, which
704                         // is what bzip2 does too. If we get SIGPIPE, we
705                         // will handle it like other signals by setting
706                         // user_abort, and get EPIPE here.
707                         if (errno != EPIPE)
708                                 message_error(_("%s: Write error: %s"),
709                                         pair->dest_name, strerror(errno));
710
711                         return true;
712                 }
713
714                 buf += (size_t)(amount);
715                 size -= (size_t)(amount);
716         }
717
718         return false;
719 }