| 1 | // TarEntry.cs
|
|---|
| 2 | //
|
|---|
| 3 | // Copyright (C) 2001 Mike Krueger
|
|---|
| 4 | //
|
|---|
| 5 | // This program is free software; you can redistribute it and/or
|
|---|
| 6 | // modify it under the terms of the GNU General Public License
|
|---|
| 7 | // as published by the Free Software Foundation; either version 2
|
|---|
| 8 | // of the License, or (at your option) any later version.
|
|---|
| 9 | //
|
|---|
| 10 | // This program is distributed in the hope that it will be useful,
|
|---|
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 13 | // GNU General Public License for more details.
|
|---|
| 14 | //
|
|---|
| 15 | // You should have received a copy of the GNU General Public License
|
|---|
| 16 | // along with this program; if not, write to the Free Software
|
|---|
| 17 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|---|
| 18 | //
|
|---|
| 19 | // Linking this library statically or dynamically with other modules is
|
|---|
| 20 | // making a combined work based on this library. Thus, the terms and
|
|---|
| 21 | // conditions of the GNU General Public License cover the whole
|
|---|
| 22 | // combination.
|
|---|
| 23 | //
|
|---|
| 24 | // As a special exception, the copyright holders of this library give you
|
|---|
| 25 | // permission to link this library with independent modules to produce an
|
|---|
| 26 | // executable, regardless of the license terms of these independent
|
|---|
| 27 | // modules, and to copy and distribute the resulting executable under
|
|---|
| 28 | // terms of your choice, provided that you also meet, for each linked
|
|---|
| 29 | // independent module, the terms and conditions of the license of that
|
|---|
| 30 | // module. An independent module is a module which is not derived from
|
|---|
| 31 | // or based on this library. If you modify this library, you may extend
|
|---|
| 32 | // this exception to your version of the library, but you are not
|
|---|
| 33 | // obligated to do so. If you do not wish to do so, delete this
|
|---|
| 34 | // exception statement from your version.
|
|---|
| 35 |
|
|---|
| 36 | using System;
|
|---|
| 37 | using System.IO;
|
|---|
| 38 | using System.Text;
|
|---|
| 39 |
|
|---|
| 40 | namespace ICSharpCode.SharpZipLib.Tar
|
|---|
| 41 | {
|
|---|
| 42 | /// <summary>
|
|---|
| 43 | /// This class represents an entry in a Tar archive. It consists
|
|---|
| 44 | /// of the entry's header, as well as the entry's File. Entries
|
|---|
| 45 | /// can be instantiated in one of three ways, depending on how
|
|---|
| 46 | /// they are to be used.
|
|---|
| 47 | /// <p>
|
|---|
| 48 | /// TarEntries that are created from the header bytes read from
|
|---|
| 49 | /// an archive are instantiated with the TarEntry( byte[] )
|
|---|
| 50 | /// constructor. These entries will be used when extracting from
|
|---|
| 51 | /// or listing the contents of an archive. These entries have their
|
|---|
| 52 | /// header filled in using the header bytes. They also set the File
|
|---|
| 53 | /// to null, since they reference an archive entry not a file.</p>
|
|---|
| 54 | /// <p>
|
|---|
| 55 | /// TarEntries that are created from files that are to be written
|
|---|
| 56 | /// into an archive are instantiated with the CreateEntryFromFile(string)
|
|---|
| 57 | /// pseudo constructor. These entries have their header filled in using
|
|---|
| 58 | /// the File's information. They also keep a reference to the File
|
|---|
| 59 | /// for convenience when writing entries.</p>
|
|---|
| 60 | /// <p>
|
|---|
| 61 | /// Finally, TarEntries can be constructed from nothing but a name.
|
|---|
| 62 | /// This allows the programmer to construct the entry by hand, for
|
|---|
| 63 | /// instance when only an InputStream is available for writing to
|
|---|
| 64 | /// the archive, and the header information is constructed from
|
|---|
| 65 | /// other information. In this case the header fields are set to
|
|---|
| 66 | /// defaults and the File is set to null.</p>
|
|---|
| 67 | /// <see cref="TarHeader"/>
|
|---|
| 68 | /// </summary>
|
|---|
| 69 | public class TarEntry : ICloneable
|
|---|
| 70 | {
|
|---|
| 71 | #region Constructors
|
|---|
| 72 | /// <summary>
|
|---|
| 73 | /// Initialise a default instance of <see cref="TarEntry"/>.
|
|---|
| 74 | /// </summary>
|
|---|
| 75 | private TarEntry()
|
|---|
| 76 | {
|
|---|
| 77 | header = new TarHeader();
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | /// <summary>
|
|---|
| 81 | /// Construct an entry from an archive's header bytes. File is set
|
|---|
| 82 | /// to null.
|
|---|
| 83 | /// </summary>
|
|---|
| 84 | /// <param name = "headerBuffer">
|
|---|
| 85 | /// The header bytes from a tar archive entry.
|
|---|
| 86 | /// </param>
|
|---|
| 87 | public TarEntry(byte[] headerBuffer)
|
|---|
| 88 | {
|
|---|
| 89 | header = new TarHeader();
|
|---|
| 90 | header.ParseBuffer(headerBuffer);
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | /// <summary>
|
|---|
| 94 | /// Construct a TarEntry using the <paramref name="header">header</paramref> provided
|
|---|
| 95 | /// </summary>
|
|---|
| 96 | /// <param name="header">Header details for entry</param>
|
|---|
| 97 | public TarEntry(TarHeader header)
|
|---|
| 98 | {
|
|---|
| 99 | if ( header == null )
|
|---|
| 100 | {
|
|---|
| 101 | throw new ArgumentNullException("header");
|
|---|
| 102 | }
|
|---|
| 103 |
|
|---|
| 104 | this.header = (TarHeader)header.Clone();
|
|---|
| 105 | }
|
|---|
| 106 | #endregion
|
|---|
| 107 |
|
|---|
| 108 | #region ICloneable Members
|
|---|
| 109 | /// <summary>
|
|---|
| 110 | /// Clone this tar entry.
|
|---|
| 111 | /// </summary>
|
|---|
| 112 | /// <returns>Returns a clone of this entry.</returns>
|
|---|
| 113 | public object Clone()
|
|---|
| 114 | {
|
|---|
| 115 | TarEntry entry = new TarEntry();
|
|---|
| 116 | entry.file = file;
|
|---|
| 117 | entry.header = (TarHeader)header.Clone();
|
|---|
| 118 | entry.Name = Name;
|
|---|
| 119 | return entry;
|
|---|
| 120 | }
|
|---|
| 121 | #endregion
|
|---|
| 122 |
|
|---|
| 123 | /// <summary>
|
|---|
| 124 | /// Construct an entry with only a <paramref name="name">name</paramref>.
|
|---|
| 125 | /// This allows the programmer to construct the entry's header "by hand".
|
|---|
| 126 | /// </summary>
|
|---|
| 127 | /// <param name="name">The name to use for the entry</param>
|
|---|
| 128 | /// <returns>Returns the newly created <see cref="TarEntry"/></returns>
|
|---|
| 129 | public static TarEntry CreateTarEntry(string name)
|
|---|
| 130 | {
|
|---|
| 131 | TarEntry entry = new TarEntry();
|
|---|
| 132 | TarEntry.NameTarHeader(entry.header, name);
|
|---|
| 133 | return entry;
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | /// <summary>
|
|---|
| 137 | /// Construct an entry for a file. File is set to file, and the
|
|---|
| 138 | /// header is constructed from information from the file.
|
|---|
| 139 | /// </summary>
|
|---|
| 140 | /// <param name = "fileName">The file name that the entry represents.</param>
|
|---|
| 141 | /// <returns>Returns the newly created <see cref="TarEntry"/></returns>
|
|---|
| 142 | public static TarEntry CreateEntryFromFile(string fileName)
|
|---|
| 143 | {
|
|---|
| 144 | TarEntry entry = new TarEntry();
|
|---|
| 145 | entry.GetFileTarHeader(entry.header, fileName);
|
|---|
| 146 | return entry;
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | /// <summary>
|
|---|
| 150 | /// Determine if the two entries are equal. Equality is determined
|
|---|
| 151 | /// by the header names being equal.
|
|---|
| 152 | /// </summary>
|
|---|
| 153 | /// <param name="obj">The <see cref="Object"/> to compare with the current Object.</param>
|
|---|
| 154 | /// <returns>
|
|---|
| 155 | /// True if the entries are equal; false if not.
|
|---|
| 156 | /// </returns>
|
|---|
| 157 | public override bool Equals(object obj)
|
|---|
| 158 | {
|
|---|
| 159 | TarEntry localEntry = obj as TarEntry;
|
|---|
| 160 |
|
|---|
| 161 | if ( localEntry != null )
|
|---|
| 162 | {
|
|---|
| 163 | return Name.Equals(localEntry.Name);
|
|---|
| 164 | }
|
|---|
| 165 | return false;
|
|---|
| 166 | }
|
|---|
| 167 |
|
|---|
| 168 | /// <summary>
|
|---|
| 169 | /// Derive a Hash value for the current <see cref="Object"/>
|
|---|
| 170 | /// </summary>
|
|---|
| 171 | /// <returns>A Hash code for the current <see cref="Object"/></returns>
|
|---|
| 172 | public override int GetHashCode()
|
|---|
| 173 | {
|
|---|
| 174 | return Name.GetHashCode();
|
|---|
| 175 | }
|
|---|
| 176 |
|
|---|
| 177 | /// <summary>
|
|---|
| 178 | /// Determine if the given entry is a descendant of this entry.
|
|---|
| 179 | /// Descendancy is determined by the name of the descendant
|
|---|
| 180 | /// starting with this entry's name.
|
|---|
| 181 | /// </summary>
|
|---|
| 182 | /// <param name = "toTest">
|
|---|
| 183 | /// Entry to be checked as a descendent of this.
|
|---|
| 184 | /// </param>
|
|---|
| 185 | /// <returns>
|
|---|
| 186 | /// True if entry is a descendant of this.
|
|---|
| 187 | /// </returns>
|
|---|
| 188 | public bool IsDescendent(TarEntry toTest)
|
|---|
| 189 | {
|
|---|
| 190 | if ( toTest == null ) {
|
|---|
| 191 | throw new ArgumentNullException("toTest");
|
|---|
| 192 | }
|
|---|
| 193 |
|
|---|
| 194 | return toTest.Name.StartsWith(Name);
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 | /// <summary>
|
|---|
| 198 | /// Get this entry's header.
|
|---|
| 199 | /// </summary>
|
|---|
| 200 | /// <returns>
|
|---|
| 201 | /// This entry's TarHeader.
|
|---|
| 202 | /// </returns>
|
|---|
| 203 | public TarHeader TarHeader
|
|---|
| 204 | {
|
|---|
| 205 | get {
|
|---|
| 206 | return header;
|
|---|
| 207 | }
|
|---|
| 208 | }
|
|---|
| 209 |
|
|---|
| 210 | /// <summary>
|
|---|
| 211 | /// Get/Set this entry's name.
|
|---|
| 212 | /// </summary>
|
|---|
| 213 | public string Name
|
|---|
| 214 | {
|
|---|
| 215 | get {
|
|---|
| 216 | return header.Name;
|
|---|
| 217 | }
|
|---|
| 218 | set {
|
|---|
| 219 | header.Name = value;
|
|---|
| 220 | }
|
|---|
| 221 | }
|
|---|
| 222 |
|
|---|
| 223 | /// <summary>
|
|---|
| 224 | /// Get/set this entry's user id.
|
|---|
| 225 | /// </summary>
|
|---|
| 226 | public int UserId
|
|---|
| 227 | {
|
|---|
| 228 | get {
|
|---|
| 229 | return header.UserId;
|
|---|
| 230 | }
|
|---|
| 231 | set {
|
|---|
| 232 | header.UserId = value;
|
|---|
| 233 | }
|
|---|
| 234 | }
|
|---|
| 235 |
|
|---|
| 236 | /// <summary>
|
|---|
| 237 | /// Get/set this entry's group id.
|
|---|
| 238 | /// </summary>
|
|---|
| 239 | public int GroupId
|
|---|
| 240 | {
|
|---|
| 241 | get {
|
|---|
| 242 | return header.GroupId;
|
|---|
| 243 | }
|
|---|
| 244 | set {
|
|---|
| 245 | header.GroupId = value;
|
|---|
| 246 | }
|
|---|
| 247 | }
|
|---|
| 248 |
|
|---|
| 249 | /// <summary>
|
|---|
| 250 | /// Get/set this entry's user name.
|
|---|
| 251 | /// </summary>
|
|---|
| 252 | public string UserName
|
|---|
| 253 | {
|
|---|
| 254 | get {
|
|---|
| 255 | return header.UserName;
|
|---|
| 256 | }
|
|---|
| 257 | set {
|
|---|
| 258 | header.UserName = value;
|
|---|
| 259 | }
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | /// <summary>
|
|---|
| 263 | /// Get/set this entry's group name.
|
|---|
| 264 | /// </summary>
|
|---|
| 265 | public string GroupName
|
|---|
| 266 | {
|
|---|
| 267 | get {
|
|---|
| 268 | return header.GroupName;
|
|---|
| 269 | }
|
|---|
| 270 | set {
|
|---|
| 271 | header.GroupName = value;
|
|---|
| 272 | }
|
|---|
| 273 | }
|
|---|
| 274 |
|
|---|
| 275 | /// <summary>
|
|---|
| 276 | /// Convenience method to set this entry's group and user ids.
|
|---|
| 277 | /// </summary>
|
|---|
| 278 | /// <param name="userId">
|
|---|
| 279 | /// This entry's new user id.
|
|---|
| 280 | /// </param>
|
|---|
| 281 | /// <param name="groupId">
|
|---|
| 282 | /// This entry's new group id.
|
|---|
| 283 | /// </param>
|
|---|
| 284 | public void SetIds(int userId, int groupId)
|
|---|
| 285 | {
|
|---|
| 286 | UserId = userId;
|
|---|
| 287 | GroupId = groupId;
|
|---|
| 288 | }
|
|---|
| 289 |
|
|---|
| 290 | /// <summary>
|
|---|
| 291 | /// Convenience method to set this entry's group and user names.
|
|---|
| 292 | /// </summary>
|
|---|
| 293 | /// <param name="userName">
|
|---|
| 294 | /// This entry's new user name.
|
|---|
| 295 | /// </param>
|
|---|
| 296 | /// <param name="groupName">
|
|---|
| 297 | /// This entry's new group name.
|
|---|
| 298 | /// </param>
|
|---|
| 299 | public void SetNames(string userName, string groupName)
|
|---|
| 300 | {
|
|---|
| 301 | UserName = userName;
|
|---|
| 302 | GroupName = groupName;
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | /// <summary>
|
|---|
| 306 | /// Get/Set the modification time for this entry
|
|---|
| 307 | /// </summary>
|
|---|
| 308 | public DateTime ModTime {
|
|---|
| 309 | get {
|
|---|
| 310 | return header.ModTime;
|
|---|
| 311 | }
|
|---|
| 312 | set {
|
|---|
| 313 | header.ModTime = value;
|
|---|
| 314 | }
|
|---|
| 315 | }
|
|---|
| 316 |
|
|---|
| 317 | /// <summary>
|
|---|
| 318 | /// Get this entry's file.
|
|---|
| 319 | /// </summary>
|
|---|
| 320 | /// <returns>
|
|---|
| 321 | /// This entry's file.
|
|---|
| 322 | /// </returns>
|
|---|
| 323 | public string File {
|
|---|
| 324 | get {
|
|---|
| 325 | return file;
|
|---|
| 326 | }
|
|---|
| 327 | }
|
|---|
| 328 |
|
|---|
| 329 | /// <summary>
|
|---|
| 330 | /// Get/set this entry's recorded file size.
|
|---|
| 331 | /// </summary>
|
|---|
| 332 | public long Size {
|
|---|
| 333 | get {
|
|---|
| 334 | return header.Size;
|
|---|
| 335 | }
|
|---|
| 336 | set {
|
|---|
| 337 | header.Size = value;
|
|---|
| 338 | }
|
|---|
| 339 | }
|
|---|
| 340 |
|
|---|
| 341 | /// <summary>
|
|---|
| 342 | /// Return true if this entry represents a directory, false otherwise
|
|---|
| 343 | /// </summary>
|
|---|
| 344 | /// <returns>
|
|---|
| 345 | /// True if this entry is a directory.
|
|---|
| 346 | /// </returns>
|
|---|
| 347 | public bool IsDirectory {
|
|---|
| 348 | get {
|
|---|
| 349 | if (file != null) {
|
|---|
| 350 | return Directory.Exists(file);
|
|---|
| 351 | }
|
|---|
| 352 |
|
|---|
| 353 | if (header != null) {
|
|---|
| 354 | if ((header.TypeFlag == TarHeader.LF_DIR) || Name.EndsWith( "/" )) {
|
|---|
| 355 | return true;
|
|---|
| 356 | }
|
|---|
| 357 | }
|
|---|
| 358 | return false;
|
|---|
| 359 | }
|
|---|
| 360 | }
|
|---|
| 361 |
|
|---|
| 362 | /// <summary>
|
|---|
| 363 | /// Fill in a TarHeader with information from a File.
|
|---|
| 364 | /// </summary>
|
|---|
| 365 | /// <param name="header">
|
|---|
| 366 | /// The TarHeader to fill in.
|
|---|
| 367 | /// </param>
|
|---|
| 368 | /// <param name="file">
|
|---|
| 369 | /// The file from which to get the header information.
|
|---|
| 370 | /// </param>
|
|---|
| 371 | public void GetFileTarHeader(TarHeader header, string file)
|
|---|
| 372 | {
|
|---|
| 373 | if ( header == null ) {
|
|---|
| 374 | throw new ArgumentNullException("header");
|
|---|
| 375 | }
|
|---|
| 376 |
|
|---|
| 377 | if ( file == null ) {
|
|---|
| 378 | throw new ArgumentNullException("file");
|
|---|
| 379 | }
|
|---|
| 380 |
|
|---|
| 381 | this.file = file;
|
|---|
| 382 |
|
|---|
| 383 | // bugfix from torhovl from #D forum:
|
|---|
| 384 | string name = file;
|
|---|
| 385 |
|
|---|
| 386 | #if !NETCF_1_0 && !NETCF_2_0
|
|---|
| 387 | // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
|
|---|
| 388 | if (name.IndexOf(Environment.CurrentDirectory) == 0) {
|
|---|
| 389 | name = name.Substring(Environment.CurrentDirectory.Length);
|
|---|
| 390 | }
|
|---|
| 391 | #endif
|
|---|
| 392 |
|
|---|
| 393 | /*
|
|---|
| 394 | if (Path.DirectorySeparatorChar == '\\')
|
|---|
| 395 | {
|
|---|
| 396 | // check if the OS is Windows
|
|---|
| 397 | // Strip off drive letters!
|
|---|
| 398 | if (name.Length > 2)
|
|---|
| 399 | {
|
|---|
| 400 | char ch1 = name[0];
|
|---|
| 401 | char ch2 = name[1];
|
|---|
| 402 |
|
|---|
| 403 | if (ch2 == ':' && Char.IsLetter(ch1))
|
|---|
| 404 | {
|
|---|
| 405 | name = name.Substring(2);
|
|---|
| 406 | }
|
|---|
| 407 | }
|
|---|
| 408 | }
|
|---|
| 409 | */
|
|---|
| 410 |
|
|---|
| 411 | name = name.Replace(Path.DirectorySeparatorChar, '/');
|
|---|
| 412 |
|
|---|
| 413 | // No absolute pathnames
|
|---|
| 414 | // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
|
|---|
| 415 | // so we loop on starting /'s.
|
|---|
| 416 | while (name.StartsWith("/")) {
|
|---|
| 417 | name = name.Substring(1);
|
|---|
| 418 | }
|
|---|
| 419 |
|
|---|
| 420 | header.LinkName = String.Empty;
|
|---|
| 421 | header.Name = name;
|
|---|
| 422 |
|
|---|
| 423 | if (Directory.Exists(file)) {
|
|---|
| 424 | header.Mode = 1003; // Magic number for security access for a UNIX filesystem
|
|---|
| 425 | header.TypeFlag = TarHeader.LF_DIR;
|
|---|
| 426 | if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') {
|
|---|
| 427 | header.Name = header.Name + "/";
|
|---|
| 428 | }
|
|---|
| 429 |
|
|---|
| 430 | header.Size = 0;
|
|---|
| 431 | } else {
|
|---|
| 432 | header.Mode = 33216; // Magic number for security access for a UNIX filesystem
|
|---|
| 433 | header.TypeFlag = TarHeader.LF_NORMAL;
|
|---|
| 434 | header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
|
|---|
| 435 | }
|
|---|
| 436 |
|
|---|
| 437 | header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
|
|---|
| 438 | header.DevMajor = 0;
|
|---|
| 439 | header.DevMinor = 0;
|
|---|
| 440 | }
|
|---|
| 441 |
|
|---|
| 442 | /// <summary>
|
|---|
| 443 | /// Get entries for all files present in this entries directory.
|
|---|
| 444 | /// If this entry doesnt represent a directory zero entries are returned.
|
|---|
| 445 | /// </summary>
|
|---|
| 446 | /// <returns>
|
|---|
| 447 | /// An array of TarEntry's for this entry's children.
|
|---|
| 448 | /// </returns>
|
|---|
| 449 | public TarEntry[] GetDirectoryEntries()
|
|---|
| 450 | {
|
|---|
| 451 | if ( (file == null) || !Directory.Exists(file)) {
|
|---|
| 452 | return new TarEntry[0];
|
|---|
| 453 | }
|
|---|
| 454 |
|
|---|
| 455 | string[] list = Directory.GetFileSystemEntries(file);
|
|---|
| 456 | TarEntry[] result = new TarEntry[list.Length];
|
|---|
| 457 |
|
|---|
| 458 | for (int i = 0; i < list.Length; ++i) {
|
|---|
| 459 | result[i] = TarEntry.CreateEntryFromFile(list[i]);
|
|---|
| 460 | }
|
|---|
| 461 |
|
|---|
| 462 | return result;
|
|---|
| 463 | }
|
|---|
| 464 |
|
|---|
| 465 | /// <summary>
|
|---|
| 466 | /// Write an entry's header information to a header buffer.
|
|---|
| 467 | /// </summary>
|
|---|
| 468 | /// <param name = "outBuffer">
|
|---|
| 469 | /// The tar entry header buffer to fill in.
|
|---|
| 470 | /// </param>
|
|---|
| 471 | public void WriteEntryHeader(byte[] outBuffer)
|
|---|
| 472 | {
|
|---|
| 473 | header.WriteHeader(outBuffer);
|
|---|
| 474 | }
|
|---|
| 475 |
|
|---|
| 476 | /// <summary>
|
|---|
| 477 | /// Convenience method that will modify an entry's name directly
|
|---|
| 478 | /// in place in an entry header buffer byte array.
|
|---|
| 479 | /// </summary>
|
|---|
| 480 | /// <param name="buffer">
|
|---|
| 481 | /// The buffer containing the entry header to modify.
|
|---|
| 482 | /// </param>
|
|---|
| 483 | /// <param name="newName">
|
|---|
| 484 | /// The new name to place into the header buffer.
|
|---|
| 485 | /// </param>
|
|---|
| 486 | static public void AdjustEntryName(byte[] buffer, string newName)
|
|---|
| 487 | {
|
|---|
| 488 | int offset = 0;
|
|---|
| 489 | TarHeader.GetNameBytes(newName, buffer, offset, TarHeader.NAMELEN);
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | /// <summary>
|
|---|
| 493 | /// Fill in a TarHeader given only the entry's name.
|
|---|
| 494 | /// </summary>
|
|---|
| 495 | /// <param name="header">
|
|---|
| 496 | /// The TarHeader to fill in.
|
|---|
| 497 | /// </param>
|
|---|
| 498 | /// <param name="name">
|
|---|
| 499 | /// The tar entry name.
|
|---|
| 500 | /// </param>
|
|---|
| 501 | static public void NameTarHeader(TarHeader header, string name)
|
|---|
| 502 | {
|
|---|
| 503 | if ( header == null ) {
|
|---|
| 504 | throw new ArgumentNullException("header");
|
|---|
| 505 | }
|
|---|
| 506 |
|
|---|
| 507 | if ( name == null ) {
|
|---|
| 508 | throw new ArgumentNullException("name");
|
|---|
| 509 | }
|
|---|
| 510 |
|
|---|
| 511 | bool isDir = name.EndsWith("/");
|
|---|
| 512 |
|
|---|
| 513 | header.Name = name;
|
|---|
| 514 | header.Mode = isDir ? 1003 : 33216;
|
|---|
| 515 | header.UserId = 0;
|
|---|
| 516 | header.GroupId = 0;
|
|---|
| 517 | header.Size = 0;
|
|---|
| 518 |
|
|---|
| 519 | header.ModTime = DateTime.UtcNow;
|
|---|
| 520 |
|
|---|
| 521 | header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;
|
|---|
| 522 |
|
|---|
| 523 | header.LinkName = String.Empty;
|
|---|
| 524 | header.UserName = String.Empty;
|
|---|
| 525 | header.GroupName = String.Empty;
|
|---|
| 526 |
|
|---|
| 527 | header.DevMajor = 0;
|
|---|
| 528 | header.DevMinor = 0;
|
|---|
| 529 | }
|
|---|
| 530 |
|
|---|
| 531 | #region Instance Fields
|
|---|
| 532 | /// <summary>
|
|---|
| 533 | /// The name of the file this entry represents or null if the entry is not based on a file.
|
|---|
| 534 | /// </summary>
|
|---|
| 535 | string file;
|
|---|
| 536 |
|
|---|
| 537 | /// <summary>
|
|---|
| 538 | /// The entry's header information.
|
|---|
| 539 | /// </summary>
|
|---|
| 540 | TarHeader header;
|
|---|
| 541 | #endregion
|
|---|
| 542 | }
|
|---|
| 543 | }
|
|---|
| 544 |
|
|---|
| 545 |
|
|---|
| 546 |
|
|---|
| 547 | /* The original Java file had this header:
|
|---|
| 548 | *
|
|---|
| 549 | ** Authored by Timothy Gerard Endres
|
|---|
| 550 | ** <mailto:time@gjt.org> <http://www.trustice.com>
|
|---|
| 551 | **
|
|---|
| 552 | ** This work has been placed into the public domain.
|
|---|
| 553 | ** You may use this work in any way and for any purpose you wish.
|
|---|
| 554 | **
|
|---|
| 555 | ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
|
|---|
| 556 | ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
|
|---|
| 557 | ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
|
|---|
| 558 | ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
|
|---|
| 559 | ** REDISTRIBUTION OF THIS SOFTWARE.
|
|---|
| 560 | **
|
|---|
| 561 | */
|
|---|