Esempio n. 1
0
        /// <summary>
        /// Fill in a TarHeader with information from a File.
        /// </summary>
        /// <param name="header">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="file">
        /// The file from which to get the header information.
        /// </param>
        public void GetFileTarHeader(TarHeader header, string file)
        {
            if ( header == null ) {
                throw new ArgumentNullException("header");
            }

            if ( file == null ) {
                throw new ArgumentNullException("file");
            }

            this.file = file;

            // bugfix from torhovl from #D forum:
            string name = file;

            #if !NETCF_1_0 && !NETCF_2_0
            // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
            if (name.IndexOf(Environment.CurrentDirectory) == 0) {
                name = name.Substring(Environment.CurrentDirectory.Length);
            }
            #endif

            /*
            if (Path.DirectorySeparatorChar == '\\')
            {
                // check if the OS is Windows
                // Strip off drive letters!
                if (name.Length > 2)
                {
                    char ch1 = name[0];
                    char ch2 = name[1];

                    if (ch2 == ':' && Char.IsLetter(ch1))
                    {
                        name = name.Substring(2);
                    }
                }
            }
            */

            name = name.Replace(Path.DirectorySeparatorChar, '/');

            // No absolute pathnames
            // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
            // so we loop on starting /'s.
            while (name.StartsWith("/")) {
                name = name.Substring(1);
            }

            header.LinkName = String.Empty;
            header.Name     = name;

            if (Directory.Exists(file)) {
                header.Mode     = 1003; // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_DIR;
                if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') {
                    header.Name = header.Name + "/";
                }

                header.Size     = 0;
            } else {
                header.Mode     = 33216; // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_NORMAL;
                header.Size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
            header.DevMajor = 0;
            header.DevMinor = 0;
        }
Esempio n. 2
0
        /// <summary>
        /// Fill in a TarHeader given only the entry's name.
        /// </summary>
        /// <param name="header">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="name">
        /// The tar entry name.
        /// </param>
        public static void NameTarHeader(TarHeader header, string name)
        {
            if ( header == null ) {
                throw new ArgumentNullException("header");
            }

            if ( name == null ) {
                throw new ArgumentNullException("name");
            }

            bool isDir = name.EndsWith("/");

            header.Name = name;
            header.Mode = isDir ? 1003 : 33216;
            header.UserId   = 0;
            header.GroupId  = 0;
            header.Size     = 0;

            header.ModTime  = DateTime.UtcNow;

            header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;

            header.LinkName  = String.Empty;
            header.UserName  = String.Empty;
            header.GroupName = String.Empty;

            header.DevMajor = 0;
            header.DevMinor = 0;
        }
Esempio n. 3
0
 /// <summary>
 /// Initialise a default instance of <see cref="TarEntry"/>.
 /// </summary>
 private TarEntry()
 {
     header = new TarHeader();
 }
Esempio n. 4
0
        /// <summary>
        /// Construct a TarEntry using the <paramref name="header">header</paramref> provided
        /// </summary>
        /// <param name="header">Header details for entry</param>
        public TarEntry(TarHeader header)
        {
            if ( header == null )
            {
                throw new ArgumentNullException("header");
            }

            this.header = (TarHeader)header.Clone();
        }
Esempio n. 5
0
 /// <summary>
 /// Construct an entry from an archive's header bytes. File is set
 /// to null.
 /// </summary>
 /// <param name = "headerBuffer">
 /// The header bytes from a tar archive entry.
 /// </param>
 public TarEntry(byte[] headerBuffer)
 {
     header = new TarHeader();
     header.ParseBuffer(headerBuffer);
 }
Esempio n. 6
0
        /// <summary>
        /// Get the next entry in this tar archive. This will skip
        /// over any remaining data in the current entry, if there
        /// is one, and place the input stream at the header of the
        /// next entry, and read the header and instantiate a new
        /// TarEntry from the header bytes and return that entry.
        /// If there are no more entries in the archive, null will
        /// be returned to indicate that the end of the archive has
        /// been reached.
        /// </summary>
        /// <returns>
        /// The next TarEntry in the archive, or null.
        /// </returns>
        public TarEntry GetNextEntry()
        {
            if (this.hasHitEOF) {
                return null;
            }

            if (this.currentEntry != null) {
                SkipToNextEntry();
            }

            byte[] headerBuf = this.buffer.ReadBlock();

            if (headerBuf == null) {
                this.hasHitEOF = true;
            } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) {
                this.hasHitEOF = true;
            }

            if (this.hasHitEOF) {
                this.currentEntry = null;
            } else {
                try {
                    TarHeader header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    if ( !header.IsChecksumValid )
                    {
                        throw new TarException("Header checksum is invalid");
                    }
                    this.entryOffset = 0;
                    this.entrySize = header.Size;

                    StringBuilder longName = null;

                    if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) {

                        byte[] nameBuffer = new byte[TarBuffer.BlockSize];
                        long numToRead = this.entrySize;

                        longName = new StringBuilder();

                        while (numToRead > 0) {
                            int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead));

                            if (numRead == -1) {
                                throw new InvalidHeaderException("Failed to read long name entry");
                            }

                            longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_GHDR) {  // POSIX global extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_XHDR) {  // POSIX extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag != TarHeader.LF_NORMAL &&
                               header.TypeFlag != TarHeader.LF_OLDNORM &&
                               header.TypeFlag != TarHeader.LF_DIR) {
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }

                    if (this.entryFactory == null) {
                        this.currentEntry = new TarEntry(headerBuf);
                        if (longName != null) {
                            currentEntry.Name = longName.ToString();
                        }
                    } else {
                        this.currentEntry = this.entryFactory.CreateEntry(headerBuf);
                    }

                    // Magic was checked here for 'ustar' but there are multiple valid possibilities
                    // so this is not done anymore.

                    this.entryOffset = 0;

                    // TODO: Review How do we resolve this discrepancy?!
                    this.entrySize = this.currentEntry.Size;
                } catch (InvalidHeaderException ex) {
                    this.entrySize = 0;
                    this.entryOffset = 0;
                    this.currentEntry = null;
                    string errorText = string.Format("Bad header in record {0} block {1} {2}",
                        buffer.CurrentRecord, buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return this.currentEntry;
        }