001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.compress.archivers.dump;
020
021import java.io.IOException;
022import java.util.Date;
023
024import org.apache.commons.compress.archivers.zip.ZipEncoding;
025
026/**
027 * This class represents identifying information about a Dump archive volume.
028 * It consists the archive's dump date, label, hostname, device name and possibly
029 * last mount point plus the volume's volume id andfirst record number.
030 *
031 * For the corresponding C structure see the header of {@link DumpArchiveEntry}.
032 */
033public class DumpArchiveSummary {
034    private long dumpDate;
035    private long previousDumpDate;
036    private int volume;
037    private String label;
038    private int level;
039    private String filesys;
040    private String devname;
041    private String hostname;
042    private int flags;
043    private int firstrec;
044    private int ntrec;
045
046    DumpArchiveSummary(final byte[] buffer, final ZipEncoding encoding) throws IOException {
047        dumpDate = 1000L * DumpArchiveUtil.convert32(buffer, 4);
048        previousDumpDate = 1000L * DumpArchiveUtil.convert32(buffer, 8);
049        volume = DumpArchiveUtil.convert32(buffer, 12);
050        label = DumpArchiveUtil.decode(encoding, buffer, 676, DumpArchiveConstants.LBLSIZE).trim();
051        level = DumpArchiveUtil.convert32(buffer, 692);
052        filesys = DumpArchiveUtil.decode(encoding, buffer, 696, DumpArchiveConstants.NAMELEN).trim();
053        devname = DumpArchiveUtil.decode(encoding, buffer, 760, DumpArchiveConstants.NAMELEN).trim();
054        hostname = DumpArchiveUtil.decode(encoding, buffer, 824, DumpArchiveConstants.NAMELEN).trim();
055        flags = DumpArchiveUtil.convert32(buffer, 888);
056        firstrec = DumpArchiveUtil.convert32(buffer, 892);
057        ntrec = DumpArchiveUtil.convert32(buffer, 896);
058
059        //extAttributes = DumpArchiveUtil.convert32(buffer, 900);
060    }
061
062    /**
063     * Get the date of this dump.
064     * @return the date of this dump.
065     */
066    public Date getDumpDate() {
067        return new Date(dumpDate);
068    }
069
070    /**
071     * Set dump date.
072     * @param dumpDate the dump date
073     */
074    public void setDumpDate(final Date dumpDate) {
075        this.dumpDate = dumpDate.getTime();
076    }
077
078    /**
079     * Get the date of the previous dump at this level higher.
080     * @return dumpdate may be null
081     */
082    public Date getPreviousDumpDate() {
083        return new Date(previousDumpDate);
084    }
085
086    /**
087     * Set previous dump date.
088     * @param previousDumpDate the previous dump dat
089     */
090    public void setPreviousDumpDate(final Date previousDumpDate) {
091        this.previousDumpDate = previousDumpDate.getTime();
092    }
093
094    /**
095     * Get volume (tape) number.
096     * @return volume (tape) number.
097     */
098    public int getVolume() {
099        return volume;
100    }
101
102    /**
103     * Set volume (tape) number.
104     * @param volume the volume number
105     */
106    public void setVolume(final int volume) {
107        this.volume = volume;
108    }
109
110    /**
111     * Get the level of this dump. This is a number between 0 and 9, inclusive,
112     * and a level 0 dump is a complete dump of the partition. For any other dump
113     * 'n' this dump contains all files that have changed since the last dump
114     * at this level or lower. This is used to support different levels of
115     * incremental backups.
116     * @return dump level
117     */
118    public int getLevel() {
119        return level;
120    }
121
122    /**
123     * Set level.
124     * @param level the level
125     */
126    public void setLevel(final int level) {
127        this.level = level;
128    }
129
130    /**
131     * Get dump label. This may be autogenerated or it may be specified
132     * bu the user.
133     * @return dump label
134     */
135    public String getLabel() {
136        return label;
137    }
138
139    /**
140     * Set dump label.
141     * @param label the label
142     */
143    public void setLabel(final String label) {
144        this.label = label;
145    }
146
147    /**
148     * Get the last mountpoint, e.g., /home.
149     * @return last mountpoint
150     */
151    public String getFilesystem() {
152        return filesys;
153    }
154
155    /**
156     * Set the last mountpoint.
157     * @param filesystem the last mountpoint
158     */
159    public void setFilesystem(final String filesystem) {
160        this.filesys = filesystem;
161    }
162
163    /**
164     * Get the device name, e.g., /dev/sda3 or /dev/mapper/vg0-home.
165     * @return device name
166     */
167    public String getDevname() {
168        return devname;
169    }
170
171    /**
172     * Set the device name.
173     * @param devname the device name
174     */
175    public void setDevname(final String devname) {
176        this.devname = devname;
177    }
178
179    /**
180     * Get the hostname of the system where the dump was performed.
181     * @return hostname the host name
182     */
183    public String getHostname() {
184        return hostname;
185    }
186
187    /**
188     * Set the hostname.
189     * @param hostname the host name
190     */
191    public void setHostname(final String hostname) {
192        this.hostname = hostname;
193    }
194
195    /**
196     * Get the miscellaneous flags. See below.
197     * @return flags
198     */
199    public int getFlags() {
200        return flags;
201    }
202
203    /**
204     * Set the miscellaneous flags.
205     * @param flags flags
206     */
207    public void setFlags(final int flags) {
208        this.flags = flags;
209    }
210
211    /**
212     * Get the inode of the first record on this volume.
213     * @return inode of the first record on this volume.
214     */
215    public int getFirstRecord() {
216        return firstrec;
217    }
218
219    /**
220     * Set the inode of the first record.
221     * @param firstrec the first record
222     */
223    public void setFirstRecord(final int firstrec) {
224        this.firstrec = firstrec;
225    }
226
227    /**
228     * Get the number of records per tape block. This is typically
229     * between 10 and 32.
230     * @return the number of records per tape block
231     */
232    public int getNTRec() {
233        return ntrec;
234    }
235
236    /**
237     * Set the number of records per tape block.
238     * @param ntrec the number of records per tape block
239     */
240    public void setNTRec(final int ntrec) {
241        this.ntrec = ntrec;
242    }
243
244    /**
245     * Is this the new header format? (We do not currently support the
246     * old format.)
247     *
248     * @return true if using new header format
249     */
250    public boolean isNewHeader() {
251        return (flags & 0x0001) == 0x0001;
252    }
253
254    /**
255     * Is this the new inode format? (We do not currently support the
256     * old format.)
257     * @return true if using new inode format
258     */
259    public boolean isNewInode() {
260        return (flags & 0x0002) == 0x0002;
261    }
262
263    /**
264     * Is this volume compressed? N.B., individual blocks may or may not be compressed.
265     * The first block is never compressed.
266     * @return true if volume is compressed
267     */
268    public boolean isCompressed() {
269        return (flags & 0x0080) == 0x0080;
270    }
271
272    /**
273     * Does this volume only contain metadata?
274     * @return true if volume only contains meta-data
275     */
276    public boolean isMetaDataOnly() {
277        return (flags & 0x0100) == 0x0100;
278    }
279
280    /**
281     * Does this volume cotain extended attributes.
282     * @return true if volume cotains extended attributes.
283     */
284    public boolean isExtendedAttributes() {
285        return (flags & 0x8000) == 0x8000;
286    }
287
288    @Override
289    public int hashCode() {
290        int hash = 17;
291
292        if (label != null) {
293            hash = label.hashCode();
294        }
295
296        hash += 31 * dumpDate;
297
298        if (hostname != null) {
299            hash = (31 * hostname.hashCode()) + 17;
300        }
301
302        if (devname != null) {
303            hash = (31 * devname.hashCode()) + 17;
304        }
305
306        return hash;
307    }
308
309    @Override
310    public boolean equals(final Object o) {
311        if (this == o) {
312            return true;
313        }
314
315        if (o == null || !o.getClass().equals(getClass())) {
316            return false;
317        }
318
319        final DumpArchiveSummary rhs = (DumpArchiveSummary) o;
320
321        if (dumpDate != rhs.dumpDate) {
322            return false;
323        }
324
325        if ((getHostname() == null) ||
326                !getHostname().equals(rhs.getHostname())) {
327            return false;
328        }
329
330        if ((getDevname() == null) || !getDevname().equals(rhs.getDevname())) {
331            return false;
332        }
333
334        return true;
335    }
336}