Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 367   Methods: 19
NCLOC: 121   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AsiExtraField.java 100% 100% 100% 100%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.zip;
 56   
 
 57   
 import java.util.zip.CRC32;
 58   
 import java.util.zip.ZipException;
 59   
 
 60   
 /**
 61   
  * Adds Unix file permission and UID/GID fields as well as symbolic
 62   
  * link handling.
 63   
  *
 64   
  * <p>This class uses the ASi extra field in the format:
 65   
  * <pre>
 66   
  *         Value         Size            Description
 67   
  *         -----         ----            -----------
 68   
  * (Unix3) 0x756e        Short           tag for this extra block type
 69   
  *         TSize         Short           total data size for this block
 70   
  *         CRC           Long            CRC-32 of the remaining data
 71   
  *         Mode          Short           file permissions
 72   
  *         SizDev        Long            symlink'd size OR major/minor dev num
 73   
  *         UID           Short           user ID
 74   
  *         GID           Short           group ID
 75   
  *         (var.)        variable        symbolic link filename
 76   
  * </pre>
 77   
  * taken from appnote.iz (Info-ZIP note, 981119) found at <a
 78   
  * href="ftp://ftp.uu.net/pub/archiving/zip/doc/">ftp://ftp.uu.net/pub/archiving/zip/doc/</a></p>
 79   
 
 80   
  *
 81   
  * <p>Short is two bytes and Long is four bytes in big endian byte and
 82   
  * word order, device numbers are currently not supported.</p>
 83   
  *
 84   
  * @author Stefan Bodewig
 85   
  * @version $Revision: 1.5 $
 86   
  */
 87   
 public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
 88   
 
 89   
     private static final ZipShort HEADER_ID = new ZipShort(0x756E);
 90   
 
 91   
     /**
 92   
      * Standard Unix stat(2) file mode.
 93   
      *
 94   
      * @since 1.1
 95   
      */
 96   
     private int mode = 0;
 97   
     /**
 98   
      * User ID.
 99   
      *
 100   
      * @since 1.1
 101   
      */
 102   
     private int uid = 0;
 103   
     /**
 104   
      * Group ID.
 105   
      *
 106   
      * @since 1.1
 107   
      */
 108   
     private int gid = 0;
 109   
     /**
 110   
      * File this entry points to, if it is a symbolic link.
 111   
      *
 112   
      * <p>empty string - if entry is not a symbolic link.</p>
 113   
      *
 114   
      * @since 1.1
 115   
      */
 116   
     private String link = "";
 117   
     /**
 118   
      * Is this an entry for a directory?
 119   
      *
 120   
      * @since 1.1
 121   
      */
 122   
     private boolean dirFlag = false;
 123   
 
 124   
     /**
 125   
      * Instance used to calculate checksums.
 126   
      *
 127   
      * @since 1.1
 128   
      */
 129   
     private CRC32 crc = new CRC32();
 130   
 
 131  14
     public AsiExtraField() {
 132   
     }
 133   
 
 134   
     /**
 135   
      * The Header-ID.
 136   
      *
 137   
      * @since 1.1
 138   
      */
 139  15
     public ZipShort getHeaderId() {
 140  15
         return HEADER_ID;
 141   
     }
 142   
 
 143   
     /**
 144   
      * Length of the extra field in the local file data - without
 145   
      * Header-ID or length specifier.
 146   
      *
 147   
      * @since 1.1
 148   
      */
 149  27
     public ZipShort getLocalFileDataLength() {
 150  27
         return new ZipShort(4         // CRC
 151   
                           + 2         // Mode
 152   
                           + 4         // SizDev
 153   
                           + 2         // UID
 154   
                           + 2         // GID
 155   
                           + getLinkedFile().getBytes().length);
 156   
     }
 157   
 
 158   
     /**
 159   
      * Delegate to local file data.
 160   
      *
 161   
      * @since 1.1
 162   
      */
 163  2
     public ZipShort getCentralDirectoryLength() {
 164  2
         return getLocalFileDataLength();
 165   
     }
 166   
 
 167   
     /**
 168   
      * The actual data to put into local file data - without Header-ID
 169   
      * or length specifier.
 170   
      *
 171   
      * @since 1.1
 172   
      */
 173  10
     public byte[] getLocalFileDataData() {
 174   
         // CRC will be added later
 175  10
         byte[] data = new byte[getLocalFileDataLength().getValue() - 4];
 176  10
         System.arraycopy((new ZipShort(getMode())).getBytes(), 0, data, 0, 2);
 177   
 
 178  10
         byte[] linkArray = getLinkedFile().getBytes();
 179  10
         System.arraycopy((new ZipLong(linkArray.length)).getBytes(),
 180   
                          0, data, 2, 4);
 181   
 
 182  10
         System.arraycopy((new ZipShort(getUserId())).getBytes(), 
 183   
                          0, data, 6, 2);
 184  10
         System.arraycopy((new ZipShort(getGroupId())).getBytes(),
 185   
                          0, data, 8, 2);
 186   
 
 187  10
         System.arraycopy(linkArray, 0, data, 10, linkArray.length);
 188   
 
 189  10
         crc.reset();
 190  10
         crc.update(data);
 191  10
         long checksum = crc.getValue();
 192   
 
 193  10
         byte[] result = new byte[data.length + 4];
 194  10
         System.arraycopy((new ZipLong(checksum)).getBytes(), 0, result, 0, 4);
 195  10
         System.arraycopy(data, 0, result, 4, data.length);
 196  10
         return result;
 197   
     }
 198   
 
 199   
     /**
 200   
      * Delegate to local file data.
 201   
      *
 202   
      * @since 1.1
 203   
      */
 204  1
     public byte[] getCentralDirectoryData() {
 205  1
         return getLocalFileDataData();
 206   
     }
 207   
 
 208   
     /**
 209   
      * Set the user id.
 210   
      *
 211   
      * @since 1.1
 212   
      */
 213  1
     public void setUserId(int uid) {
 214  1
         this.uid = uid;
 215   
     }
 216   
 
 217   
     /**
 218   
      * Get the user id.
 219   
      *
 220   
      * @since 1.1
 221   
      */
 222  13
     public int getUserId() {
 223  13
         return uid;
 224   
     }
 225   
 
 226   
     /**
 227   
      * Set the group id.
 228   
      *
 229   
      * @since 1.1
 230   
      */
 231  1
     public void setGroupId(int gid) {
 232  1
         this.gid = gid;
 233   
     }
 234   
 
 235   
     /**
 236   
      * Get the group id.
 237   
      *
 238   
      * @since 1.1
 239   
      */
 240  13
     public int getGroupId() {
 241  13
         return gid;
 242   
     }
 243   
 
 244   
     /**
 245   
      * Indicate that this entry is a symbolic link to the given filename.
 246   
      *
 247   
      * @param name Name of the file this entry links to, empty String
 248   
      *             if it is not a symbolic link.
 249   
      *
 250   
      * @since 1.1
 251   
      */
 252  2
     public void setLinkedFile(String name) {
 253  2
         link = name;
 254  2
         mode = getMode(mode);
 255   
     }
 256   
 
 257   
     /**
 258   
      * Name of linked file
 259   
      *
 260   
      * @return name of the file this entry links to if it is a
 261   
      *         symbolic link, the empty string otherwise.
 262   
      *
 263   
      * @since 1.1
 264   
      */
 265  74
     public String getLinkedFile() {
 266  74
         return link;
 267   
     }
 268   
 
 269   
     /**
 270   
      * Is this entry a symbolic link?
 271   
      *
 272   
      * @since 1.1
 273   
      */
 274  36
     public boolean isLink() {
 275  36
         return getLinkedFile().length() != 0;
 276   
     }
 277   
 
 278   
     /**
 279   
      * File mode of this file.
 280   
      *
 281   
      * @since 1.1
 282   
      */
 283  10
     public void setMode(int mode) {
 284  10
         this.mode = getMode(mode);
 285   
     }
 286   
 
 287   
     /**
 288   
      * File mode of this file.
 289   
      *
 290   
      * @since 1.1
 291   
      */
 292  17
     public int getMode() {
 293  17
         return mode;
 294   
     }
 295   
 
 296   
     /**
 297   
      * Indicate whether this entry is a directory.
 298   
      *
 299   
      * @since 1.1
 300   
      */
 301  9
     public void setDirectory(boolean dirFlag) {
 302  9
         this.dirFlag = dirFlag;
 303  9
         mode = getMode(mode);
 304   
     }
 305   
 
 306   
     /**
 307   
      * Is this entry a directory?
 308   
      *
 309   
      * @since 1.1
 310   
      */
 311  20
     public boolean isDirectory() {
 312  20
         return dirFlag && !isLink();
 313   
     }
 314   
 
 315   
     /**
 316   
      * Populate data from this array as if it was in local file data.
 317   
      *
 318   
      * @since 1.1
 319   
      */
 320  6
     public void parseFromLocalFileData(byte[] data, int offset, int length)
 321   
         throws ZipException {
 322   
 
 323  6
         long givenChecksum = (new ZipLong(data, offset)).getValue();
 324  6
         byte[] tmp = new byte[length - 4];
 325  6
         System.arraycopy(data, offset + 4, tmp, 0, length - 4);
 326  6
         crc.reset();
 327  6
         crc.update(tmp);
 328  6
         long realChecksum = crc.getValue();
 329  6
         if (givenChecksum != realChecksum) {
 330  1
             throw new ZipException("bad CRC checksum " 
 331   
                                    + Long.toHexString(givenChecksum)
 332   
                                    + " instead of " 
 333   
                                    + Long.toHexString(realChecksum));
 334   
         }
 335   
         
 336  5
         int newMode = (new ZipShort(tmp, 0)).getValue();
 337  5
         byte[] linkArray = new byte[(int) (new ZipLong(tmp, 2)).getValue()];
 338  5
         uid = (new ZipShort(tmp, 6)).getValue();
 339  5
         gid = (new ZipShort(tmp, 8)).getValue();
 340   
 
 341  5
         if (linkArray.length == 0) {
 342  4
             link = "";
 343   
         } else {
 344  1
             System.arraycopy(tmp, 10, linkArray, 0, linkArray.length);
 345  1
             link = new String(linkArray);
 346   
         }
 347  5
         setDirectory((newMode & DIR_FLAG) != 0);
 348  5
         setMode(newMode);
 349   
     }
 350   
 
 351   
     /**
 352   
      * Get the file mode for given permissions with the correct file type.
 353   
      *
 354   
      * @since 1.1
 355   
      */
 356  21
     protected int getMode(int mode) {
 357  21
         int type = FILE_FLAG;
 358  21
         if (isLink()) {
 359  4
             type = LINK_FLAG;
 360  17
         } else if (isDirectory()) {
 361  11
             type = DIR_FLAG;
 362   
         }
 363  21
         return type | (mode & PERM_MASK);
 364   
     }
 365   
     
 366   
 }
 367