use of diskCacheV111.util.FsPath in project dcache by dCache.
the class ChimeraNameSpaceProvider method writeExtendedAttribute.
public void writeExtendedAttribute(Subject subject, FsPath path, String name, byte[] value, SetExtendedAttributeMode mode) throws CacheException {
try {
ExtendedInode target = pathToInode(subject, path.toString());
if (!Subjects.isExemptFromNamespaceChecks(subject)) {
FileAttributes attributes = getFileAttributesForPermissionHandler(target);
if (target.isDirectory()) {
if (_permissionHandler.canCreateFile(subject, attributes) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Access denied");
}
} else {
if (_permissionHandler.canWriteFile(subject, attributes) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Access denied");
}
}
}
FileSystemProvider.SetXattrMode m;
switch(mode) {
case CREATE:
m = FileSystemProvider.SetXattrMode.CREATE;
break;
case REPLACE:
m = FileSystemProvider.SetXattrMode.REPLACE;
break;
case EITHER:
m = FileSystemProvider.SetXattrMode.EITHER;
break;
default:
throw new RuntimeException();
}
_fs.setXattr(target, name, value, m);
} catch (NoXdataChimeraException e) {
throw new NoAttributeCacheException(e.getMessage(), e);
} catch (FileExistsChimeraFsException e) {
throw new AttributeExistsCacheException(e.getMessage(), e);
} catch (FileNotFoundChimeraFsException e) {
throw new FileNotFoundCacheException("No such file " + path);
} catch (ChimeraFsException e) {
throw new CacheException("Failed to list extended attributes: " + Exceptions.messageOrClassName(e), e);
}
}
use of diskCacheV111.util.FsPath in project dcache by dCache.
the class ChimeraNameSpaceProvider method removeLabel.
/**
* @param subject The user making the request. Remove a label from a file.
* @param path The file from which the label is deleted.
* @param label The name of the label to remove.
* @throws FileNotFoundCacheException if the path does not exist.
* @throws PermissionDeniedCacheException if the user is not allowed to remove the label.
* @throws CacheException a generic failure in removing the labe.
*/
public void removeLabel(Subject subject, FsPath path, String label) throws CacheException {
try {
ExtendedInode target = pathToInode(subject, path.toString());
if (!Subjects.isRoot(subject)) {
FileAttributes attributes = getFileAttributesForPermissionHandler(target);
if (target.isDirectory()) {
throw new NotFileCacheException("Directory object cannot have a label.");
} else {
if (_permissionHandler.canWriteFile(subject, attributes) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Access denied");
}
}
}
_fs.removeLabel(target, label);
} catch (FileNotFoundChimeraFsException e) {
throw new FileNotFoundCacheException("No such file " + path);
} catch (ChimeraFsException e) {
throw new CacheException("Failed to remove the label: " + Exceptions.messageOrClassName(e), e);
}
}
use of diskCacheV111.util.FsPath in project dcache by dCache.
the class ChimeraNameSpaceProvider method commitUpload.
@Override
public FileAttributes commitUpload(Subject subject, FsPath temporaryPath, FsPath finalPath, Set<CreateOption> options, Set<FileAttribute> attributesToFetch) throws CacheException {
try {
FsPath temporaryDir = getParentOfFile(temporaryPath);
FsPath finalDir = getParentOfFile(finalPath);
checkIsTemporaryDirectory(temporaryPath, temporaryDir);
/* File must have been created...
*/
ExtendedInode uploadDirInode;
ExtendedInode temporaryDirInode;
ExtendedInode inodeOfFile;
try {
uploadDirInode = new ExtendedInode(_fs, _fs.path2inode(temporaryDir.parent().toString()));
temporaryDirInode = uploadDirInode.inodeOf(temporaryDir.name(), STAT);
inodeOfFile = temporaryDirInode.inodeOf(temporaryPath.name(), STAT);
} catch (FileNotFoundChimeraFsException e) {
throw new FileNotFoundCacheException("No such file or directory: " + temporaryPath, e);
}
/* ...and upload must have completed...
*/
ImmutableList<StorageLocatable> locations = inodeOfFile.getLocations();
if (locations.isEmpty()) {
throw new FileIsNewCacheException("Upload has not completed.");
}
/* ...and it must have the correct size.
*/
ImmutableList<String> size = inodeOfFile.getTag(TAG_EXPECTED_SIZE);
if (!size.isEmpty()) {
long expectedSize = Long.parseLong(size.get(0));
long actualSize = inodeOfFile.statCache().getSize();
if (expectedSize != actualSize) {
throw new FileCorruptedCacheException(expectedSize, actualSize);
}
}
/* Target directory must exist.
*/
ExtendedInode finalDirInode;
try {
finalDirInode = new ExtendedInode(_fs, _fs.path2inode(finalDir.toString()));
} catch (FileNotFoundChimeraFsException e) {
throw new FileNotFoundCacheException("No such file or directory: " + finalDir, e);
}
/* File must not exist unless overwrite is enabled.
*/
try {
ExtendedInode inodeOfExistingFile = finalDirInode.inodeOf(finalPath.name(), STAT);
if (!options.contains(CreateOption.OVERWRITE_EXISTING)) {
throw new FileExistsCacheException("File exists: " + finalPath);
}
/* User must be authorized to delete existing file.
*/
if (!Subjects.isExemptFromNamespaceChecks(subject)) {
FileAttributes attributesOfParent = getFileAttributesForPermissionHandler(finalDirInode);
FileAttributes attributesOfFile = getFileAttributesForPermissionHandler(inodeOfExistingFile);
if (_permissionHandler.canDeleteFile(subject, attributesOfParent, attributesOfFile) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Overwrite denied: " + finalPath);
}
}
} catch (FileNotFoundChimeraFsException ignored) {
}
/* Read file attributes before moving the file. Otherwise the cached parent will
* be gone.
*/
FileAttributes attributes = getFileAttributes(inodeOfFile, attributesToFetch);
/* File is moved to correct directory.
*/
_fs.rename(inodeOfFile, temporaryDirInode, temporaryPath.name(), finalDirInode, finalPath.name());
/* Delete temporary upload directory and any files in it.
*/
removeRecursively(uploadDirInode, temporaryDir.name(), temporaryDirInode, i -> {
});
return attributes;
} catch (ChimeraFsException e) {
throw new CacheException(CacheException.UNEXPECTED_SYSTEM_EXCEPTION, e.getMessage());
} catch (NumberFormatException e) {
throw new FileCorruptedCacheException("Failed to commit file: " + e.getMessage());
}
}
use of diskCacheV111.util.FsPath in project dcache by dCache.
the class ChimeraNameSpaceProvider method createUploadPath.
@Override
public FsPath createUploadPath(Subject subject, FsPath path, FsPath rootPath, Long size, AccessLatency al, RetentionPolicy rp, String spaceToken, Set<CreateOption> options) throws CacheException {
checkState(_uploadDirectory != null, "Upload directory is not configured.");
try {
/* Parent directory must exist.
*/
ExtendedInode parentOfPath = options.contains(CreateOption.CREATE_PARENTS) ? installDirectory(subject, path.parent(), INHERIT_MODE) : lookupDirectory(subject, path.parent());
FileAttributes attributesOfParent = !Subjects.isExemptFromNamespaceChecks(subject) ? getFileAttributesForPermissionHandler(parentOfPath) : null;
/* File must not exist unless overwrite is enabled.
*/
try {
ExtendedInode inodeOfPath = parentOfPath.inodeOf(path.name(), STAT);
if (!options.contains(CreateOption.OVERWRITE_EXISTING) || (inodeOfPath.statCache().getMode() & UnixPermission.S_TYPE) != UnixPermission.S_IFREG) {
throw new FileExistsCacheException("File exists: " + path);
}
/* User must be authorized to delete existing file.
*/
if (!Subjects.isExemptFromNamespaceChecks(subject)) {
FileAttributes attributesOfPath = getFileAttributesForPermissionHandler(inodeOfPath);
if (_permissionHandler.canDeleteFile(subject, attributesOfParent, attributesOfPath) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Access denied: " + path);
}
}
} catch (FileNotFoundChimeraFsException ignored) {
}
/* User must be authorized to create file.
*/
if (!Subjects.isExemptFromNamespaceChecks(subject)) {
if (_permissionHandler.canCreateFile(subject, attributesOfParent) != ACCESS_ALLOWED) {
throw new PermissionDeniedCacheException("Access denied: " + path);
}
}
/* Attributes are inherited from real parent directory.
*/
int mode = parentOfPath.statCache().getMode() & UnixPermission.S_PERMS;
int gid;
if ((mode & UnixPermission.S_ISGID) != 0) {
gid = parentOfPath.statCache().getGid();
} else if (Subjects.isNobody(subject) || _inheritFileOwnership) {
gid = parentOfPath.statCache().getGid();
} else {
gid = Ints.checkedCast(Subjects.getPrimaryGid(subject));
}
int uid;
if (Subjects.isNobody(subject) || _inheritFileOwnership) {
uid = parentOfPath.statCache().getUid();
} else {
uid = Ints.checkedCast(Subjects.getUid(subject));
}
/* ACLs are copied from real parent to the temporary upload directory
* such that the upload is allowed (in case write permissions rely
* on ACLs) and such that the file will inherit the correct ACLs.
*/
List<ACE> acl = _fs.getACL(parentOfPath);
/* The temporary upload directory has the same tags as the real parent,
* except target file specific properties are stored as tags local to
* the upload directory.
*/
Map<String, byte[]> tags = Maps.newHashMap(parentOfPath.getTags());
if (spaceToken != null) {
tags.put(TAG_WRITE_TOKEN, spaceToken.getBytes(UTF_8));
/* If client provides space token to upload to, the access latency and
* retention policy tags of the upload directory must be disregarded.
*/
tags.remove(TAG_ACCESS_LATENCY);
tags.remove(TAG_RETENTION_POLICY);
}
if (al != null) {
tags.put(TAG_ACCESS_LATENCY, al.toString().getBytes(UTF_8));
}
if (rp != null) {
tags.put(TAG_RETENTION_POLICY, rp.toString().getBytes(UTF_8));
}
if (size != null) {
tags.put(TAG_EXPECTED_SIZE, size.toString().getBytes(UTF_8));
}
tags.put(TAG_PATH, path.toString().getBytes(UTF_8));
/* Upload directory may optionally be relative to the user's root path. Whether
* that's the case depends on if the configured upload directory is an absolute
* or relative path.
*/
FsPath uploadDirectory = rootPath.resolve(_uploadDirectory);
if (_uploadSubDirectory != null) {
uploadDirectory = uploadDirectory.chroot(String.format(_uploadSubDirectory, threadId.get()));
}
/* Upload directory must exist and have the right permissions.
*/
ExtendedInode inodeOfUploadDir = installSystemDirectory(uploadDirectory, 0711, Collections.emptyList(), Collections.emptyMap());
if (inodeOfUploadDir.statCache().getUid() != 0) {
LOGGER.error("Owner must be root: {}", uploadDirectory);
throw new CacheException("Owner must be root: " + uploadDirectory);
}
if ((inodeOfUploadDir.statCache().getMode() & UnixPermission.S_PERMS) != 0711) {
LOGGER.error("File mode must be 0711: {}", uploadDirectory);
throw new CacheException("File mode must be 0711: " + uploadDirectory);
}
/* Use cryptographically strong pseudo random UUID to create temporary upload directory.
*/
UUID uuid = UUID.randomUUID();
_fs.mkdir(inodeOfUploadDir, uuid.toString(), uid, gid, mode, acl, tags);
return uploadDirectory.child(uuid.toString()).child(path.name());
} catch (ChimeraFsException e) {
LOGGER.error("Problem with database: {}", e.getMessage());
throw new CacheException(CacheException.UNEXPECTED_SYSTEM_EXCEPTION, e.getMessage());
}
}
use of diskCacheV111.util.FsPath in project dcache by dCache.
the class ChimeraNameSpaceProvider method checkIsTemporaryDirectory.
protected void checkIsTemporaryDirectory(FsPath temporaryPath, FsPath temporaryDir) throws NotFileCacheException, InvalidMessageCacheException {
checkState(_uploadDirectory != null, "Upload directory is not configured.");
FsPath temporaryDirContainer = getParentOfFile(temporaryDir);
if (_uploadDirectory.startsWith("/")) {
if (!temporaryDirContainer.hasPrefix(FsPath.create(_uploadDirectory))) {
throw new InvalidMessageCacheException(temporaryPath + " is not part of the " + _uploadDirectory + " tree.");
}
} else {
if (!temporaryDirContainer.contains(_uploadDirectory)) {
throw new InvalidMessageCacheException(temporaryPath + " is not part of the " + _uploadDirectory + " tree.");
}
}
if (temporaryDir.isRoot()) {
throw new InvalidMessageCacheException("A temporary upload path cannot be in the root directory.");
}
}
Aggregations