diff options
author | Xavier Ducrohet <xav@android.com> | 2012-10-24 17:02:47 -0700 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2012-10-24 17:02:47 -0700 |
commit | 0a6d8750c4330ad793f3beae670eb21e0e1d401b (patch) | |
tree | 226729f6f6181b6c867fbf6d06e89ca8a1dfcf6d /src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java | |
parent | 6950a7fcfda2d03446514e315b6bf6bd5c476496 (diff) | |
parent | 67fe07b509b35defe3a8c80d65ad5ae859ac354a (diff) | |
download | fat32lib-0a6d8750c4330ad793f3beae670eb21e0e1d401b.tar.gz |
Merge changes I50294fcc,Ie59bda0c
* changes:
Added LGPL 2.1 NOTICE file and MODULE_LICENSE
External library with modifications. fat32-lib. Signed-off-by: Dan Galpin <dgalpin@google.com>
Diffstat (limited to 'src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java')
-rw-r--r-- | src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java b/src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java new file mode 100644 index 0000000..0882516 --- /dev/null +++ b/src/main/java/de/waldheinz/fs/fat/FatLfnDirectoryEntry.java @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2003-2009 JNode.org + * 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package de.waldheinz.fs.fat; + +import de.waldheinz.fs.AbstractFsObject; +import de.waldheinz.fs.FsDirectoryEntry; +import de.waldheinz.fs.ReadOnlyException; +import java.io.IOException; + +/** + * Represents an entry in a {@link FatLfnDirectory}. Besides implementing the + * {@link FsDirectoryEntry} interface for FAT file systems, it allows access + * to the {@link #setArchiveFlag(boolean) archive}, + * {@link #setHiddenFlag(boolean) hidden}, + * {@link #setReadOnlyFlag(boolean) read-only} and + * {@link #setSystemFlag(boolean) system} flags specifed for the FAT file + * system. + * + * @author Matthias Treydte <waldheinz at gmail.com> + * @since 0.6 + */ +public final class FatLfnDirectoryEntry + extends AbstractFsObject + implements FsDirectoryEntry { + + final FatDirectoryEntry realEntry; + + private FatLfnDirectory parent; + private String fileName; + + FatLfnDirectoryEntry(String name, ShortName sn, + FatLfnDirectory parent, boolean directory) { + + super(false); + + this.parent = parent; + this.fileName = name; + + final long now = System.currentTimeMillis(); + this.realEntry = FatDirectoryEntry.create(directory); + this.realEntry.setShortName(sn); + this.realEntry.setCreated(now); + this.realEntry.setLastAccessed(now); + } + + FatLfnDirectoryEntry(FatLfnDirectory parent, + FatDirectoryEntry realEntry, String fileName) { + + super(parent.isReadOnly()); + + this.parent = parent; + this.realEntry = realEntry; + this.fileName = fileName; + } + + static FatLfnDirectoryEntry extract( + FatLfnDirectory dir, int offset, int len) { + + final FatDirectoryEntry realEntry = dir.dir.getEntry(offset + len - 1); + final String fileName; + + if (len == 1) { + /* this is just an old plain 8.3 entry */ + fileName = realEntry.getShortName().asSimpleString(); + } else { + /* stored in reverse order */ + final StringBuilder name = new StringBuilder(13 * (len - 1)); + + for (int i = len - 2; i >= 0; i--) { + FatDirectoryEntry entry = dir.dir.getEntry(i + offset); + name.append(entry.getLfnPart()); + } + + fileName = name.toString().trim(); + } + + return new FatLfnDirectoryEntry(dir, realEntry, fileName); + } + + /** + * Returns if this directory entry has the FAT "hidden" flag set. + * + * @return if this is a hidden directory entry + * @see #setHiddenFlag(boolean) + */ + public boolean isHiddenFlag() { + return this.realEntry.isHiddenFlag(); + } + + /** + * Sets the "hidden" flag on this {@code FatLfnDirectoryEntry} to the + * specified value. + * + * @param hidden if this entry should have the hidden flag set + * @throws ReadOnlyException if this entry is read-only + * @see #isHiddenFlag() + */ + public void setHiddenFlag(boolean hidden) throws ReadOnlyException { + checkWritable(); + + this.realEntry.setHiddenFlag(hidden); + } + + /** + * Returns if this directory entry has the FAT "system" flag set. + * + * @return if this is a "system" directory entry + * @see #setSystemFlag(boolean) + */ + public boolean isSystemFlag() { + return this.realEntry.isSystemFlag(); + } + + /** + * Sets the "system" flag on this {@code FatLfnDirectoryEntry} to the + * specified value. + * + * @param systemEntry if this entry should have the system flag set + * @throws ReadOnlyException if this entry is read-only + * @see #isSystemFlag() + */ + public void setSystemFlag(boolean systemEntry) throws ReadOnlyException { + checkWritable(); + + this.realEntry.setSystemFlag(systemEntry); + } + + /** + * Returns if this directory entry has the FAT "read-only" flag set. This + * entry may still modified if {@link #isReadOnly()} returns {@code true}. + * + * @return if this entry has the read-only flag set + * @see #setReadOnlyFlag(boolean) + */ + public boolean isReadOnlyFlag() { + return this.realEntry.isReadonlyFlag(); + } + + /** + * Sets the "read only" flag on this {@code FatLfnDirectoryEntry} to the + * specified value. This method only modifies the read-only flag as + * specified by the FAT file system, which is essentially ignored by the + * fat32-lib. The true indicator if it is possible to alter this + * + * @param readOnly if this entry should be flagged as read only + * @throws ReadOnlyException if this entry is read-only as given by + * {@link #isReadOnly()} method + * @see #isReadOnlyFlag() + */ + public void setReadOnlyFlag(boolean readOnly) throws ReadOnlyException { + checkWritable(); + + this.realEntry.setReadonlyFlag(readOnly); + } + + /** + * Returns if this directory entry has the FAT "archive" flag set. + * + * @return if this entry has the archive flag set + */ + public boolean isArchiveFlag() { + return this.realEntry.isArchiveFlag(); + } + + /** + * Sets the "archive" flag on this {@code FatLfnDirectoryEntry} to the + * specified value. + * + * @param archive if this entry should have the archive flag set + * @throws ReadOnlyException if this entry is + * {@link #isReadOnly() read-only} + */ + public void setArchiveFlag(boolean archive) throws ReadOnlyException { + checkWritable(); + + this.realEntry.setArchiveFlag(archive); + } + + private int totalEntrySize() { + int result = (fileName.length() / 13) + 1; + + if ((fileName.length() % 13) != 0) { + result++; + } + + return result; + } + + FatDirectoryEntry[] compactForm() { + if (this.realEntry.getShortName().equals(ShortName.DOT) || + this.realEntry.getShortName().equals(ShortName.DOT_DOT) || + this.realEntry.hasShortNameOnly) { + /* the dot entries must not have a LFN */ + return new FatDirectoryEntry[]{this.realEntry}; + } + + final int totalEntrySize = totalEntrySize(); + + final FatDirectoryEntry[] entries = + new FatDirectoryEntry[totalEntrySize]; + + final byte checkSum = this.realEntry.getShortName().checkSum(); + int j = 0; + + for (int i = totalEntrySize - 2; i > 0; i--) { + entries[i] = createPart(fileName.substring(j * 13, j * 13 + 13), + j + 1, checkSum, false); + j++; + } + + entries[0] = createPart(fileName.substring(j * 13), + j + 1, checkSum, true); + + entries[totalEntrySize - 1] = this.realEntry; + + return entries; + } + + @Override + public String getName() { + checkValid(); + + return fileName; + } + + @Override + public void setName(String newName) throws IOException { + checkWritable(); + + if (!this.parent.isFreeName(newName)) { + throw new IOException( + "the name \"" + newName + "\" is already in use"); + } + + this.parent.unlinkEntry(this); + this.fileName = newName; + this.parent.linkEntry(this); + } + + /** + * Moves this entry to a new directory under the specified name. + * + * @param target the direcrory where this entry should be moved to + * @param newName the new name under which this entry will be accessible + * in the target directory + * @throws IOException on error moving this entry + * @throws ReadOnlyException if this directory is read-only + */ + public void moveTo(FatLfnDirectory target, String newName) + throws IOException, ReadOnlyException { + + checkWritable(); + + if (!target.isFreeName(newName)) { + throw new IOException( + "the name \"" + newName + "\" is already in use"); + } + + this.parent.unlinkEntry(this); + this.parent = target; + this.fileName = newName; + this.parent.linkEntry(this); + } + + @Override + public void setLastModified(long lastModified) { + checkWritable(); + realEntry.setLastModified(lastModified); + } + + @Override + public FatFile getFile() throws IOException { + return parent.getFile(realEntry); + } + + @Override + public FatLfnDirectory getDirectory() throws IOException { + return parent.getDirectory(realEntry); + } + + @Override + public String toString() { + return "LFN = " + fileName + " / SFN = " + realEntry.getShortName(); + } + + private static FatDirectoryEntry createPart(String subName, + int ordinal, byte checkSum, boolean isLast) { + + final char[] unicodechar = new char[13]; + subName.getChars(0, subName.length(), unicodechar, 0); + + for (int i=subName.length(); i < 13; i++) { + if (i==subName.length()) { + unicodechar[i] = 0x0000; + } else { + unicodechar[i] = 0xffff; + } + } + + final byte[] rawData = new byte[FatDirectoryEntry.SIZE]; + + if (isLast) { + LittleEndian.setInt8(rawData, 0, ordinal + (1 << 6)); + } else { + LittleEndian.setInt8(rawData, 0, ordinal); + } + + LittleEndian.setInt16(rawData, 1, unicodechar[0]); + LittleEndian.setInt16(rawData, 3, unicodechar[1]); + LittleEndian.setInt16(rawData, 5, unicodechar[2]); + LittleEndian.setInt16(rawData, 7, unicodechar[3]); + LittleEndian.setInt16(rawData, 9, unicodechar[4]); + LittleEndian.setInt8(rawData, 11, 0x0f); // this is the hidden + // attribute tag for + // lfn + LittleEndian.setInt8(rawData, 12, 0); // reserved + LittleEndian.setInt8(rawData, 13, checkSum); // checksum + LittleEndian.setInt16(rawData, 14, unicodechar[5]); + LittleEndian.setInt16(rawData, 16, unicodechar[6]); + LittleEndian.setInt16(rawData, 18, unicodechar[7]); + LittleEndian.setInt16(rawData, 20, unicodechar[8]); + LittleEndian.setInt16(rawData, 22, unicodechar[9]); + LittleEndian.setInt16(rawData, 24, unicodechar[10]); + LittleEndian.setInt16(rawData, 26, 0); // sector... unused + LittleEndian.setInt16(rawData, 28, unicodechar[11]); + LittleEndian.setInt16(rawData, 30, unicodechar[12]); + + return new FatDirectoryEntry(rawData, false); + } + + @Override + public long getLastModified() throws IOException { + return realEntry.getLastModified(); + } + + @Override + public long getCreated() throws IOException { + return realEntry.getCreated(); + } + + @Override + public long getLastAccessed() throws IOException { + return realEntry.getLastAccessed(); + } + + @Override + public boolean isFile() { + return realEntry.isFile(); + } + + @Override + public boolean isDirectory() { + return realEntry.isDirectory(); + } + + @Override + public boolean isDirty() { + return realEntry.isDirty(); + } + +} |