diff options
Diffstat (limited to 'gnu/usr.bin/cpio')
-rw-r--r-- | gnu/usr.bin/cpio/copyout.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/gnu/usr.bin/cpio/copyout.c b/gnu/usr.bin/cpio/copyout.c index 35682e1b7453..933e4dad0778 100644 --- a/gnu/usr.bin/cpio/copyout.c +++ b/gnu/usr.bin/cpio/copyout.c @@ -35,6 +35,7 @@ static void add_link_defer (); static void writeout_other_defers (); static void writeout_final_defers(); static void writeout_defered_file (); +static int check_rdev (); /* Write out header FILE_HDR, including the file name, to file descriptor OUT_DES. */ @@ -337,6 +338,21 @@ process_copy_out () error (0, 0, "%s: file name too long", file_hdr.c_name); continue; } + switch (check_rdev (&file_hdr)) + { + case 1: + error (0, 0, "%s not dumped: major number would be truncated", + file_hdr.c_name); + continue; + case 2: + error (0, 0, "%s not dumped: minor number would be truncated", + file_hdr.c_name); + continue; + case 4: + error (0, 0, "%s not dumped: device number would be truncated", + file_hdr.c_name); + continue; + } /* Copy the named file to the output. */ switch (file_hdr.c_mode & CP_IFMT) @@ -799,3 +815,98 @@ writeout_defered_file (header, out_file_des) } return; } + +static int +check_rdev (file_hdr) + struct new_cpio_header *file_hdr; +{ + if (archive_format == arf_newascii || archive_format == arf_crcascii) + { + if ((file_hdr->c_rdev_maj & 0xFFFFFFFF) != file_hdr->c_rdev_maj) + return 1; + if ((file_hdr->c_rdev_min & 0xFFFFFFFF) != file_hdr->c_rdev_min) + return 2; + } + else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii) + { +#ifndef __MSDOS__ + dev_t rdev; + + rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min); + if (archive_format == arf_oldascii) + { + if ((rdev & 0xFFFF) != rdev) + return 4; + } + else + { + switch (file_hdr->c_mode & CP_IFMT) + { + case CP_IFCHR: + case CP_IFBLK: +#ifdef CP_IFSOCK + case CP_IFSOCK: +#endif +#ifdef CP_IFIFO + case CP_IFIFO: +#endif + /* We could handle one more bit if longs are >= 33 bits. */ + if ((rdev & 037777777777) != rdev) + return 4; + break; + default: + if ((rdev & 0xFFFF) != rdev) + return 4; + break; + } + } +#endif + } + else if (archive_format == arf_tar || archive_format == arf_ustar) + { + /* The major and minor formats are limited to 7 octal digits in ustar + format, and to_oct () adds a gratuitous trailing blank to further + limit the format to 6 octal digits. */ + if ((file_hdr->c_rdev_maj & 0777777) != file_hdr->c_rdev_maj) + return 1; + if ((file_hdr->c_rdev_min & 0777777) != file_hdr->c_rdev_min) + return 2; + } + else + { +#ifndef __MSDOS__ + dev_t rdev; + + rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min); + if (archive_format != arf_hpbinary) + { + if ((rdev & 0xFFFF) != rdev) + return 4; + } + else + { + switch (file_hdr->c_mode & CP_IFMT) + { + case CP_IFCHR: + case CP_IFBLK: +#ifdef CP_IFSOCK + case CP_IFSOCK: +#endif +#ifdef CP_IFIFO + case CP_IFIFO: +#endif + if ((rdev & 0xFFFFFFFF) != rdev) + return 4; + file_hdr->c_filesize = rdev; + rdev = makedev (0, 1); + break; + default: + if ((rdev & 0xFFFF) != rdev) + return 4; + break; + } + } +#endif + } + return 0; +} |