Skip to content

Commit aedce8a

Browse files
authored
Merge pull request #451 from SpectraLogic/metadata_dacl_parsing_bug
Metadata dacl parsing bug
2 parents e6ce51f + 11335f5 commit aedce8a

File tree

12 files changed

+448
-72
lines changed

12 files changed

+448
-72
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ project(':ds3-metadata') {
5959
project(':ds3-sdk-integration') {
6060
dependencies {
6161
compile project(':ds3-sdk')
62+
compile project(':ds3-metadata')
6263
}
6364
}
6465

ds3-metadata/src/main/java/com/spectralogic/ds3client/metadata/MetadataAccessImpl.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818

1919
import com.google.common.collect.ImmutableMap;
20+
import com.spectralogic.ds3client.helpers.FailureEventListener;
2021
import com.spectralogic.ds3client.helpers.MetadataAccess;
22+
import com.spectralogic.ds3client.helpers.events.FailureEvent;
2123
import com.spectralogic.ds3client.metadata.interfaces.MetadataStore;
2224
import com.spectralogic.ds3client.utils.Platform;
2325

@@ -28,25 +30,47 @@
2830
import java.nio.file.attribute.PosixFileAttributes;
2931
import java.util.Map;
3032

33+
import com.spectralogic.ds3client.utils.StringExtensions;
34+
3135
/**
3236
* Implementation of MetaDataAcess Interface
3337
* Used to store meta data on Server
3438
*/
3539
public class MetadataAccessImpl implements MetadataAccess {
3640
private final ImmutableMap<String, Path> fileMapper;
41+
private final FailureEventListener failureEventListener;
42+
private final String httpEndpoint;
3743

3844
public MetadataAccessImpl(final ImmutableMap<String, Path> fileMapper) {
45+
this(fileMapper, null, null);
46+
}
47+
48+
public MetadataAccessImpl(final ImmutableMap<String, Path> fileMapper,
49+
final FailureEventListener failureEventListener,
50+
final String httpEndpoint)
51+
{
3952
this.fileMapper = fileMapper;
53+
this.failureEventListener = failureEventListener;
54+
this.httpEndpoint = httpEndpoint;
4055
}
4156

4257
@Override
4358
public Map<String, String> getMetadataValue(final String filename) {
4459
final Path file = fileMapper.get(filename);
4560
try {
4661
return storeMetaData(file);
47-
} catch (final IOException e) {
48-
throw new RuntimeException("Error recording metadata.", e);
62+
} catch (final Throwable t) {
63+
if (failureEventListener != null) {
64+
failureEventListener.onFailure(FailureEvent.builder()
65+
.withObjectNamed(filename)
66+
.withCausalException(t)
67+
.doingWhat(FailureEvent.FailureActivity.RecordingMetadata)
68+
.usingSystemWithEndpoint(StringExtensions.getStringOrDefault(httpEndpoint, " "))
69+
.build());
70+
}
4971
}
72+
73+
return ImmutableMap.of();
5074
}
5175

5276
/**

ds3-metadata/src/main/java/com/spectralogic/ds3client/metadata/MetadataReceivedListenerImpl.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717

1818
import com.google.common.collect.ImmutableList;
1919
import com.spectralogic.ds3client.exceptions.AggregateException;
20+
import com.spectralogic.ds3client.helpers.FailureEventListener;
2021
import com.spectralogic.ds3client.helpers.MetadataReceivedListener;
22+
import com.spectralogic.ds3client.helpers.events.FailureEvent;
2123
import com.spectralogic.ds3client.metadata.interfaces.MetadataRestore;
2224
import com.spectralogic.ds3client.networking.Metadata;
2325
import com.spectralogic.ds3client.utils.Guard;
26+
import com.spectralogic.ds3client.utils.StringExtensions;
2427
import org.slf4j.Logger;
2528
import org.slf4j.LoggerFactory;
2629

@@ -31,19 +34,36 @@ public class MetadataReceivedListenerImpl implements MetadataReceivedListener {
3134
private final static Logger LOG = LoggerFactory.getLogger(MetadataReceivedListenerImpl.class);
3235

3336
private final String localFilePath;
34-
37+
private final FailureEventListener failureEventListener;
38+
private final String httpEndpoint;
3539

3640
public MetadataReceivedListenerImpl(final String localFilePath) {
41+
this(localFilePath, null, null);
42+
}
43+
44+
public MetadataReceivedListenerImpl(final String localFilePath,
45+
final FailureEventListener failureEventListener,
46+
final String httpEndpoint)
47+
{
3748
this.localFilePath = localFilePath;
49+
this.failureEventListener = failureEventListener;
50+
this.httpEndpoint = httpEndpoint;
3851
}
3952

4053
@Override
4154
public void metadataReceived(final String filename, final Metadata metadata) {
4255
try {
4356
final String actualFilePath = MetaDataUtil.getRealFilePath(localFilePath, filename);
4457
restoreMetaData(actualFilePath, metadata);
45-
} catch (final IOException | InterruptedException e) {
46-
throw new RuntimeException("Error restoring metadata.", e);
58+
} catch (final Throwable t) {
59+
if (failureEventListener != null) {
60+
failureEventListener.onFailure(FailureEvent.builder()
61+
.doingWhat(FailureEvent.FailureActivity.RestoringMetadata)
62+
.withCausalException(t)
63+
.withObjectNamed(filename)
64+
.usingSystemWithEndpoint(StringExtensions.getStringOrDefault(httpEndpoint, " "))
65+
.build());
66+
}
4767
}
4868
}
4969

@@ -66,23 +86,20 @@ private void restoreMetaData(final String objectName, final Metadata metadata) t
6686
try {
6787
metadataRestore.restoreUserAndOwner();
6888
} catch (final Throwable t) {
69-
LOG.error("Could not restore owner and owner information", t);
7089
exceptionBuilder.add(t);
7190
}
7291

7392
//restore creation and modified time based on OS
7493
try {
7594
metadataRestore.restoreFileTimes();
7695
} catch (final Throwable t) {
77-
LOG.error("Could not restore the file times", t);
7896
exceptionBuilder.add(t);
7997
}
8098

8199
//restore permissions based on OS
82100
try {
83101
metadataRestore.restorePermissions();
84102
} catch (final Throwable t) {
85-
LOG.error("Could not restore the file permissions", t);
86103
exceptionBuilder.add(t);
87104
}
88105

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* ******************************************************************************
3+
* Copyright 2014-2016 Spectra Logic Corporation. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
5+
* this file except in compliance with the License. A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the "license" file accompanying this file.
10+
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
12+
* specific language governing permissions and limitations under the License.
13+
* ****************************************************************************
14+
*/
15+
16+
package com.spectralogic.ds3client.metadata;
17+
18+
/**
19+
* An exception specialized to let us filter on the specific circumstance
20+
* when reading metadata from or writing metadata to a file on Windows
21+
* fails.
22+
*/
23+
public class WindowsMetadataException extends RuntimeException {
24+
public WindowsMetadataException() { }
25+
26+
public WindowsMetadataException(final String failureMessage) {
27+
super(failureMessage);
28+
}
29+
30+
public WindowsMetadataException(final String failureMessage, final Throwable cause) {
31+
super(failureMessage, cause);
32+
}
33+
34+
public WindowsMetadataException(final Throwable cause) {
35+
super(cause);
36+
}
37+
38+
protected WindowsMetadataException(final String failureMessage, final Throwable cause,
39+
final boolean enableSuppression, final boolean writableStackTrace)
40+
{
41+
super(failureMessage, cause, enableSuppression, writableStackTrace);
42+
}
43+
}

ds3-metadata/src/main/java/com/spectralogic/ds3client/metadata/WindowsMetadataRestore.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,22 @@ class WindowsMetadataRestore extends AbstractMetadataRestore {
5151

5252
@Override
5353
public void restoreUserAndOwner() throws IOException {
54-
if (storedOS != null && storedOS.equals(localOS)) {
54+
try {
55+
if (storedOS != null && storedOS.equals(localOS)) {
5556

56-
final String ownerSid = getMetadataProperty(metadata, KEY_OWNER);
57-
final String groupSid = getMetadataProperty(metadata, KEY_GROUP);
57+
final String ownerSid = getMetadataProperty(metadata, KEY_OWNER);
58+
final String groupSid = getMetadataProperty(metadata, KEY_GROUP);
5859

59-
if (!Guard.isStringNullOrEmpty(ownerSid) && !Guard.isStringNullOrEmpty(groupSid)) {
60-
setOwnerIdAndGroupId(ownerSid, groupSid);
60+
if (!Guard.isStringNullOrEmpty(ownerSid) && !Guard.isStringNullOrEmpty(groupSid)) {
61+
setOwnerIdAndGroupId(ownerSid, groupSid);
62+
} else {
63+
LOG.warn("Cannot determine owner or group settings for {}", this.objectName);
64+
}
6165
} else {
62-
LOG.warn("Cannot determine owner or group settings for {}", this.objectName);
66+
LOG.warn("The OS settings for owner and group properties cannot be restored for {}", this.objectName);
6367
}
64-
} else {
65-
LOG.warn("The OS settings for owner and group properties cannot be restored for {}", this.objectName);
68+
} catch (final Throwable t) {
69+
throw new WindowsMetadataException("Restoring user and owner.", t);
6670
}
6771
}
6872

@@ -72,12 +76,16 @@ private static String getMetadataProperty(final Metadata metadata, final String
7276

7377
@Override
7478
public void restorePermissions() throws IOException, InterruptedException {
75-
if (storedOS != null && storedOS.equals(localOS)) {
76-
setPermissionsForWindows();
77-
} else {
78-
LOG.warn("The OS settings for the file permissions cannot be restored for {}", this.objectName);
79+
try {
80+
if (storedOS != null && storedOS.equals(localOS)) {
81+
setPermissionsForWindows();
82+
} else {
83+
LOG.warn("The OS settings for the file permissions cannot be restored for {}", this.objectName);
84+
}
85+
restoreFlags();
86+
} catch (final Throwable t) {
87+
throw new WindowsMetadataException("Restoring permissions.", t);
7988
}
80-
restoreFlags();
8189
}
8290

8391
private void setPermissionsForWindows() throws IOException {

ds3-metadata/src/main/java/com/spectralogic/ds3client/metadata/WindowsMetadataStore.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,20 @@ private void saveWindowsfilePermissions(final Path file) throws IOException {
168168
final StringBuilder userDisplayList = new StringBuilder();
169169
final Map<String, Set<Integer>> stringSetMap = new HashMap<>();
170170
for (final AclEntry aclEntry : aclEntries) {
171-
userDisplay = aclEntry.principal().getName().split("\\\\")[1];
171+
/*
172+
If a file has no Windoze dacl entries, as may happen on a network-mounted file system, there won't be a principal entry.
173+
A principal is a combination of security provider, like NT AUTHORITY, and user name, e.g. NT AUTHORITY\Gracie.
174+
This code is looking for the user name -- the second half of the principal. With no principal, there is no
175+
second half of the principal.
176+
*/
177+
final String[] principalFields = aclEntry.principal().getName().split("\\\\");
178+
179+
if (principalFields.length < 2) {
180+
continue;
181+
}
182+
183+
userDisplay = principalFields[1];
184+
172185
Set<Integer> newSet = stringSetMap.get(userDisplay);
173186
aclEntryPermissions = aclEntry.permissions();
174187
if (newSet == null) {
@@ -211,8 +224,12 @@ private void saveWindowsfilePermissions(final Path file) throws IOException {
211224

212225
@Override
213226
public void saveOSSpecificMetadata(final Path file, final BasicFileAttributes attrs) throws IOException {
214-
saveWindowsfilePermissions(file);
215-
saveWindowsDescriptors(file);
216-
saveFlagMetaData(file);
227+
try {
228+
saveWindowsfilePermissions(file);
229+
saveWindowsDescriptors(file);
230+
saveFlagMetaData(file);
231+
} catch (final Throwable t) {
232+
throw new WindowsMetadataException("Saving OS-specific metadata.", t);
233+
}
217234
}
218235
}

0 commit comments

Comments
 (0)