Z      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYportableduncan@community.haskell.org Safe-Inferred((A tar archive is a sequence of entries. LThe point of this type as opposed to just using a list is that it makes the L failure case explicit. We need this because the sequence of entries we get , from reading a tarball can include errors. MIt is a concrete data type so you can manipulate it directly but it is often K clearer to use the provided functions for mapping, folding and unfolding. -Converting from a list can be done with just foldr Next Done . Converting # back into a list can be done with 7 however in that case you  must be prepared to handle the  case inherent in the  type. The Z@ instance lets you concatenate archives or append entries to an  archive. 8The tar format allows just 100 ASCII characters for the  and   entry types. JThe classic tar format allowed just 100 characters for the file name. The L USTAR format extended this with an extra 155 characters, however it uses a @ complex method of splitting the name between the two sections. IInstead of just putting any overflow into the extended area, it uses the K extended area as a prefix. The aggravating insane bit however is that the I prefix (if any) must only contain a directory prefix. That is the split N between the two areas must be on a directory separator boundary. So there is J no simple calculation to work out if a file name is too long. Instead we M have to try to find a valid split that makes the name fit in the two areas. KThe rationale presumably was to make it a bit more compatible with old tar J programs that only understand the classic format. A classic tar would be I able to extract the file name and possibly some dir prefix, but not the H full dir prefix. So the files would end up in the wrong place, but that's : probably better than ending up with the wrong names too. So it'&s understandable but rather annoying.  Tar paths use Posix format (ie '/'% directory separators), irrespective " of the local path conventions. 8 The directory separator between the prefix and name is not stored. GThere have been a number of extensions to the tar file format over the H years. They all share the basic entry fields and put more meta-data in  different extended headers. FThe GNU tar implementation also extends the classic V7 format, though G in a slightly different way from the USTAR format. In general for new  archives the standard USTAR/POSIX should be used. The "USTAR"9 format is an extension of the classic V7 format. It was G later standardised by POSIX. It has some restrictions but is the most  portable format. FThis is the classic Unix V7 tar format. It does not support owner and I group names, just numeric Ids. It also does not support device numbers. &The owner user name. Should be set to "" if unknown. 'The owner group name. Should be set to "" if unknown. (Numeric owner user id. Should be set to 0 if unknown. )Numeric owner group id. Should be set to 0 if unknown. HThe content of a tar archive entry, which depends on the type of entry. &Portable archives should contain only  and . Tar archive entry. CThe path of the file or directory within the archive. This is in a  tar-specific form. Use ' to get a native [. #The real content of the entry. For  this includes the ( file data. An entry usually contains a  or a . )File permissions (Unix style file mode). /The user and group to which this file belongs. %The time the file was last modified. %The tar format the archive is using. %+The number of seconds since the UNIX epoch 'Native [. of the file or directory within the archive. ( rw-r--r-- for normal files ) rwxr-xr-x for executable files * rwxr-xr-x for directories +An ? with all default values except for the file name and type. It  uses the portable USTAR/POSIX format (see  UstarHeader). >You can use this as a basis and override specific fields, eg: 4 (emptyEntry name HardLink) { linkTarget = target } ,A tar  for a file. JEntry fields such as file permissions and ownership have default values. MYou can use this as a basis and override specific fields. For example if you ( need an executable file you could use: < (fileEntry name content) { fileMode = executableFileMode } -A tar  for a directory. IEntry fields such as file permissions and ownership have default values. . Convert a  to a native [.  The native [7 will use the native directory separator but it is not : otherwise checked for validity or sanity. In particular: @ The tar path may be invalid as a native path, eg the file name "nul"  is not valid on Windows. 5 The tar path may be an absolute path or may contain ".." components. K For security reasons this should not usually be allowed, but it is your : responsibility to check for these conditions (eg using  checkSecurity). / Convert a  to a Unix/Posix [. The difference compared to ." is that it always returns a Unix : style path irrespective of the current operating system. This is useful to check how a $ would be interpreted on a specific 5 operating system, eg to perform portability checks. 0 Convert a  to a Windows [.  The only difference compared to . is that it always returns a B Windows style path irrespective of the current operating system. This is useful to check how a $ would be interpreted on a specific 5 operating system, eg to perform portability checks. 1Convert a native [ to a . The conversion may fail if the [ is too long. See  for a 0 description of the problem with splitting long [s. \HTake a sanitised path, split on directory separators and try to pack it * into the 155 + 100 tar file name format. JThe strategy is this: take the name-directory components in reverse order L and try to fit as many components into the 100 long name area as possible. G If all the remaining components fit in the 155 name area then we win. 2Convert a native [ to a tar . This may fail if the E string is longer than 100 characters or if it contains non-portable  characters. 3Convert a tar  to a native [. 4Convert a tar  to a Unix/Posix [. 5Convert a tar  to a Windows [. 6This is like the standard unfoldr function on lists, but for . K It includes failure as an extra possibility that the stepper function may  return. It can be used to generate ) from some other type. For example it is 1 used internally to lazily unfold entries from a ]. 7This is like the standard ^ function on lists, but for .  Compared to ^/ it takes an extra function to account for the  possibility of failure. LThis is used to consume a sequence of entries. For example it could be used H to scan a tarball for problems or to collect an index of the contents. 8This is like the standard _ function on lists, but for . It G includes failure as a extra possible outcome of the mapping function. FIf your mapping function cannot fail it may be more convenient to use  9 9Like 8. but the mapping function itself cannot fail. >`a  !"#$%&'()*+,-./018Is the path for a directory? This is needed because for  directories a  must always use a trailing /. \23456789b<`a  !"#$%&'()*+,-./0123456789"`a    !"#$%&'()*+,-./01\23456789bportableduncan@community.haskell.org Safe-Inferred:;Errors that can be encountered when parsing a Tar archive. CCConvert a data stream in the tar file format into an internal data 0 structure. Decoding errors are reported by the  constructor of the   type.  The conversion is done lazily. cde:;<=>?@ABCfghijklmnop :;<=>?@ABCced:BA@?>=<;Cfghijklmnopportableduncan@community.haskell.org Safe-InferredDJCreate the external representation of a tar archive by serialising a list  of tar entries.  The conversion is done lazily. qDrstuvwxD qDrstuvwxportableduncan@community.haskell.orgNoneEICreates a tar archive from a list of directory or files. Any directories G specified will have their contents included recursively. Paths in the 7 archive will be relative to the given base directory. MThis is a portable implementation of packing suitable for portable archives. " In particular it only constructs  and  entries. Hard M links and symbolic links are treated like ordinary files. It cannot be used M to pack directories containing recursive symbolic links. Special files like H FIFOs (named pipes), sockets or device files will also cause problems. DAn exception will be thrown for any file names that are too long to  represent as a . B This function returns results lazily. Subdirectories are scanned C and files are read one by one as the list of entries is consumed. FConstruct a tar  based on a local file. EThis sets the entry size, the data contained in the file and the file's L modification time. If the file is executable then that information is also G preserved. File ownership and detailed permissions are not preserved. # The file contents is read lazily. GConstruct a tar 4 based on a local directory (but not its contents). KThe only attribute of the directory that is used is its modification time. A Directory ownership and detailed permissions are not preserved. H&This is a utility function, much like y. The @ difference is that it includes the contents of subdirectories. JThe paths returned are all relative to the top directory. Directory paths 9 are distinguishable by having a trailing path separator  (see z). KAll directories are listed before the files that they contain. Amongst the L contents of a directory, subdirectories are listed after normal files. The N overall result is that files within a directory will be together in a single M contiguous group. This tends to improve file layout and IO performance when & creating or extracting tar archives. F This function returns results lazily. Subdirectories are not scanned E until the files entries in the parent directory have been consumed. EBase directory 8Files and directories to pack, relative to the base dir {|}F-Full path to find the file on the local disk -Path to use for the tar Entry in the archive G-Full path to find the file on the local disk -Path to use for the tar Entry in the archive H~EFGH E{|}FGH~portableduncan@community.haskell.org Safe-InferredI:The name of a platform that portability issues arise from J.Potential portability issues in a tar archive O(An error that occurs if a tar file is a "tar bomb" that would extract * files outside of the intended directory. QJErrors arising from tar file names being in some way invalid or dangerous TFThis function checks a sequence of tar entries for file name security  problems. It checks that:  file paths are not absolute 8 file paths do not contain any path components that are ".."  file names are valid MThese checks are from the perspective of the current OS. That means we check  for "C:blah" files on Windows and "/blah" files on Unix. For archive  entry types  and " the same checks are done for the M link target. A failure in any entry terminates the sequence of entries with  an error. U;This function checks a sequence of tar entries for being a "tar bomb". K This means that the tar file does not follow the standard convention that ; all entries are within a single subdirectory, e.g. a file "foo.tar" would % usually have all entries within the "foo/" subdirectory. MGiven the expected subdirectory, this function checks all entries are within  that subdirectroy. 2Note: This check must be used in conjunction with T. VKThis function checks a sequence of tar entries for a number of portability  issues. It will complain if:  The old "Unix V7" or "gnu"+ formats are used. For maximum portability  only the POSIX standard "ustar" format should be used. E A non-portable entry type is used. Only ordinary files, hard links, M symlinks and directories are portable. Device files, pipes and others are 6 not portable between all common operating systems. J Non-ASCII characters are used in file names. There is no agreed portable L convention for Unicode or other extended character sets in file names in  tar archives. L File names that would not be portable to both Unix and Windows. This check > includes characters that are valid in both systems and the '/' vs '\' $ directory separator conventions. IJKLMNOPQRSTUVIJKLMNOPQRSTUVTQSRUOPVJNMLKIIJNMLKOPQSRTUVportableduncan@community.haskell.org Safe-InferredWJCreate local files and directories based on the entries of a tar archive. EThis is a portable implementation of unpacking suitable for portable  archives. It handles  and  entries and has simulated  support for  and # entries. Links are implemented by K copying the target file. This therefore works on Windows as well as Unix. I All other entry types are ignored, that is they are not unpacked and no  exception is raised. If the 9 ends in an error then it is raised an an exception. Any C files or directories that have been unpacked before the error was I encountered will not be deleted. For this reason you may want to unpack L into an empty directory so that you can easily clean up if unpacking fails  part-way. :On its own, this function only checks for security (using T). ? You can do other checks by applying checking functions to the  that ) you pass to this function. For example:  / unpack dir (checkTarbomb expectedDir entries) KIf you care about the priority of the reported errors then you may want to  use T before U or other checks. WWWportableduncan@community.haskell.orgNone5  !"#$%&'()*+,-./012345FGH5 ' &!%$#" +,-()*FGH1./02345portableduncan@community.haskell.orgNoneX Create a new ".tar"! file from a directory of files. )It is equivalent to calling the standard tar program like so:  #$ tar -f tarball.tar -C base -c dirThis assumes a directory ./base/dir with files inside, eg  ./base/dir/foo.txt7. The file names inside the resulting tar file will be  relative to dir, eg dir/foo.txt. This is a high level " all in one"* operation. Since you may need variations J on this function it is instructive to see how it is written. It is just:  6 BS.writeFile tar . Tar.write =<< Tar.pack base paths Notes: GThe files and directories must not change during this operation or the  result is not well defined. GThe intention of this function is to create tarballs that are portable  between systems. It is not0 suitable for doing file system backups because K file ownership and permissions are not fully preserved. File ownership is K not preserved at all. File permissions are set to simple portable values:   rw-r--r-- for normal files   rwxr-xr-x for executable files   rwxr-xr-x for directories Y%Extract all the files contained in a ".tar" file. )It is equivalent to calling the standard tar program like so:  $ tar -x -f tarball.tar -C dirSo for example if the  tarball.tar file contains foo/bar.txt then this  will extract it to dir/foo/bar.txt. This is a high level " all in one"* operation. Since you may need variations J on this function it is instructive to see how it is written. It is just:  / Tar.unpack dir . Tar.read =<< BS.readFile tar Notes: LExtracting can fail for a number of reasons. The tarball may be incorrectly M formatted. There may be IO or permission errors. In such cases an exception 2 will be thrown and extraction will not continue. JSince the extraction may fail part way through it is not atomic. For this D reason you may want to extract into an empty directory and, if the 5 extraction fails, recursively delete the directory. KSecurity: only files inside the target directory will be written. Tarballs M containing entries that point outside of the tarball (either absolute paths D or relative paths) will be caught and an exception will be thrown. X Path of the ".tar" file to write. Base directory 7Files and directories to archive, relative to base dir YDestination directory Tarball #'6789:;<=>?@ABCDEWXY$XYCDEW'8976:BA@?>=<;XY      !!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVVWXYZ[\]^_`ab`cdefgh`ij`ik lmnopqrstuvwxyz{|}~ tar-0.4.0.1Codec.Archive.TarCodec.Archive.Tar.EntryCodec.Archive.Tar.CheckCodec.Archive.Tar.TypesCodec.Archive.Tar.ReadCodec.Archive.Tar.WriteCodec.Archive.Tar.PackCodec.Archive.Tar.UnpackEntriesFailDoneNext LinkTargetTarPathFormat GnuFormat UstarFormatV7Format Ownership ownerName groupNameownerIdgroupId EntryContentOtherEntryType NamedPipe BlockDeviceCharacterDeviceHardLink SymbolicLink Directory NormalFileEntry entryTarPath entryContententryPermissionsentryOwnership entryTime entryFormat PermissionsTypeCodeDevMinorDevMajor EpochTimeFileSize entryPathordinaryFilePermissionsexecutableFilePermissionsdirectoryPermissions simpleEntry fileEntrydirectoryEntry fromTarPathfromTarPathToPosixPathfromTarPathToWindowsPath toTarPath toLinkTargetfromLinkTargetfromLinkTargetToPosixPathfromLinkTargetToWindowsPath unfoldEntries foldEntries mapEntriesmapEntriesNoFail FormatErrorHeaderBadNumericEncodingUnrecognisedTarFormat NotTarFormatChecksumIncorrect TrailingJunk BadTrailer ShortTrailerTruncatedArchivereadwritepack packFileEntrypackDirectoryEntrygetDirectoryContentsRecursivePortabilityPlatformPortabilityErrorNonPortableFileNameNonPortableEntryNameCharNonPortableFileTypeNonPortableFormat TarBombError FileNameErrorAbsoluteFileNameInvalidFileName checkSecurity checkTarbombcheckPortabilityunpackcreateextractbase Data.MonoidMonoidGHC.IOFilePath splitLongPathbytestring-0.10.0.2Data.ByteString.Lazy.Internal ByteStringGHC.Basefoldrmap$fMonoidEntriesPartialOkErrorgetEntrycorrectChecksumgetOctgetBytesgetBytegetChars getStringpartial$fMonadPartial$fExceptionFormatError$fShowFormatError FieldWidthputEntry putHeaderputHeaderNoChkSum putStringputOctputChar8filldirectory-1.2.0.1System.DirectorygetDirectoryContentsfilepath-1.3.0.1System.FilePath.PosixhasTrailingPathSeparator preparePaths packPaths interleaverecurseDirectories getModTimecheckEntrySecurityshowFileNameErrorcheckEntryTarbombcheckEntryPortability checkEntries$fShowPortabilityError$fExceptionPortabilityError$fShowTarBombError$fExceptionTarBombError$fExceptionFileNameError$fShowFileNameError