From f52cac2c0ee6985dac1026f2302e2f780dbbeca5 Mon Sep 17 00:00:00 2001 From: anttil <anttil> Date: Tue, 13 Aug 2013 09:17:31 +0000 Subject: [PATCH] BIS-506 / SP-801: Zip file based archiver consistency checks SVN: 29639 --- .../server/plugins/standard/CrcProvider.java | 53 ++++++++ .../server/plugins/standard/ICrcProvider.java | 25 ++++ .../server/plugins/standard/Verifier.java | 27 ++++ .../plugins/standard/ZipFileCrcVerifier.java | 128 ++++++++++++++++++ .../standard/ZipFilePathInfoVerifier.java | 77 +++++++++++ 5 files changed, 310 insertions(+) create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java new file mode 100644 index 00000000000..38ee81ca9dd --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; + +import java.util.Map; + +import ch.systemsx.cisd.openbis.dss.generic.server.DatabaseBasedDataSetPathInfoProvider; + +/** + * @author anttil + */ +public class CrcProvider implements ICrcProvider +{ + private Map<String, Integer> checksums; + + public CrcProvider(String dataSetCode) + { + checksums = new DatabaseBasedDataSetPathInfoProvider().getDataSetChecksums(dataSetCode); + } + + @Override + public Long getCrc(String name) + { + Integer crc = checksums.get(name); + if (crc == null) + { + return null; + } else + { + return getUnsignedInt(crc); + } + } + + public static long getUnsignedInt(int x) + { + return x & 0x00000000ffffffffL; + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java new file mode 100644 index 00000000000..6003ba4b8fc --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; + +/** + * @author anttil + */ +public interface ICrcProvider +{ + Long getCrc(String name); +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java new file mode 100644 index 00000000000..ce61d68dbec --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; + +import java.util.List; + +/** + * @author anttil + */ +public interface Verifier +{ + public List<String> verify(); +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java new file mode 100644 index 00000000000..0eeb48854dc --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java @@ -0,0 +1,128 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.CRC32; +import java.util.zip.ZipException; + +import de.schlichtherle.util.zip.ZipEntry; +import de.schlichtherle.util.zip.ZipFile; + +/** + * @author anttil + */ +public class ZipFileCrcVerifier implements Verifier +{ + + private final File file; + + public ZipFileCrcVerifier(File file) + { + this.file = file; + } + + @Override + public List<String> verify() + { + List<String> errors = new ArrayList<String>(); + ZipFile zip; + try + { + zip = new ZipFile(file); + } catch (ZipException ex) + { + errors.add("Reading zip file failed: " + ex.getMessage()); + return errors; + } catch (IOException ex) + { + errors.add("Reading zip file failed: " + ex.getMessage()); + return errors; + } + + Enumeration<?> entries = zip.entries(); + while (entries.hasMoreElements()) + { + ZipEntry entry = (ZipEntry) entries.nextElement(); + errors.addAll(checkZipEntry(zip, entry)); + } + return errors; + } + + private Collection<String> checkZipEntry(ZipFile zip, ZipEntry entry) + { + InputStream input = null; + try + { + input = zip.getInputStream(entry); + + long crc = calcCRC32(input); + + if (crc != entry.getCrc()) + { + return Arrays.asList(entry.getName() + ": CRC failure (got " + Long.toHexString(crc) + ", should be " + + Long.toHexString(entry.getCrc()) + ")"); + } + + } catch (ZipException ex) + { + return Arrays.asList(ex.getMessage()); + } catch (IOException ex) + { + return Arrays.asList(entry.getName() + ": " + ex.getMessage()); + } finally + { + if (input != null) + { + try + { + input.close(); + } catch (IOException ex) + { + } + } + } + return new ArrayList<String>(); + } + + private static long calcCRC32(InputStream input) throws IOException + { + BufferedInputStream inStream = new BufferedInputStream(input); + int BLOCK_SIZE = 128 * 1024; + int len; + byte[] buffer = new byte[BLOCK_SIZE]; + + CRC32 crc32 = new CRC32(); + crc32.reset(); + + while ((len = inStream.read(buffer, 0, BLOCK_SIZE)) > 0) + { + crc32.update(buffer, 0, len); + buffer = new byte[BLOCK_SIZE]; + } + + return crc32.getValue(); + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java new file mode 100644 index 00000000000..61b570bb7af --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipException; + +import de.schlichtherle.util.zip.ZipEntry; +import de.schlichtherle.util.zip.ZipFile; + +/** + * @author anttil + */ +public class ZipFilePathInfoVerifier implements Verifier +{ + + private final File file; + + private final ICrcProvider crcProvider; + + public ZipFilePathInfoVerifier(File file, ICrcProvider crcProvider) + { + this.file = file; + this.crcProvider = crcProvider; + } + + @Override + public List<String> verify() + { + List<String> errors = new ArrayList<String>(); + ZipFile zip; + try + { + zip = new ZipFile(file); + } catch (ZipException ex) + { + errors.add("Reading zip file failed: " + ex.getMessage()); + return errors; + } catch (IOException ex) + { + errors.add("Reading zip file failed: " + ex.getMessage()); + return errors; + } + + Enumeration<?> entries = zip.entries(); + while (entries.hasMoreElements()) + { + ZipEntry entry = (ZipEntry) entries.nextElement(); + + Long externalCrc = crcProvider.getCrc(entry.getName()); + if (externalCrc != null && externalCrc != entry.getCrc()) + { + errors.add(entry.getName() + ": external CRC: " + externalCrc + ", header CRC: " + entry.getCrc()); + } + } + return errors; + } + +} -- GitLab