/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2009, Jens Kager, Fritz Praus
Copyright (C) 2008-2009, Rainhard Raschbauer
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fat;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileOutputStream extends FileStream {
private int[] buffer = new int[FatItS.BlockSize];
private DirEntry entryBuffer = new DirEntry();
private long size = 0;
private int attribs = 0;
private int startcluster = 0;
private long offset = 0;
private char[] filename = new char[255];
private int dirCluster;
/***************************************************************************
* public FileOutputStream(String file) Creates an output file stream to
* write to the file with the specified name.
*
* If the file exists but is a directory rather than a regular file, does
* not exist but cannot be created, or cannot be opened for any other reason
* then a ?????????????????????????????.
*
* Parameters: file - Directories and files are seperated with "/". Do not
* write the leading "/" in the filename string. append - if true, then
* bytes will be written to the end of the file rather than the beginning
**************************************************************************/
public FileOutputStream(int streamtype, String file, boolean append) throws IOException {
super(streamtype);
int i = 0;
char[] subdir = new char[13];
int inroot = 0;
while (i < file.length()) {
filename[i] = file.charAt(i);
i++;
}
i = 0;
FatItS.fat_init(fatlowlevel);
if (filename[0] == 0) {
throw new IOException();
}
while (filename[i] != 0) {
if (filename[i] == '/') {
inroot++;
}
i++;
}
if ((i > 12) && (inroot == 0)) {
throw new IOException();
}
i = 0;
int j = 0;
for (int b = 0; b < inroot; b++) {
j = 0;
while (filename[i] != '/') {
subdir[j] = filename[i];
if (i > 11) {
throw new IOException();
}
j++;
i++;
}
j++;
i++;
subdir[j] = 0;
entryBuffer = FatItS.fat_search_file(fatlowlevel, entryBuffer.getCluster(), subdir, entryBuffer);
}
if (inroot != 0) {
for (int b = 0; b < 13; b++) {
filename[b] = filename[b + i];
if (filename[b + i] == 0) {
inroot = 0;
break;
}
}
if (inroot != 0) {
throw new IOException();
}
}
dirCluster = entryBuffer.getCluster();
try {
entryBuffer = FatItS.fat_search_file(fatlowlevel, dirCluster, filename, entryBuffer);
} catch (FileNotFoundException exc) {
entryBuffer = FatItS.fat_add_file(fatlowlevel, dirCluster, filename, entryBuffer);
}
size = entryBuffer.getSize();
startcluster = entryBuffer.getCluster();
attribs = entryBuffer.getAttribs();
offset = 0;
if (append == false) {
size = 0;
entryBuffer = FatItS.fat_mod_file(fatlowlevel, dirCluster, filename, size, attribs, entryBuffer);
} else {
offset = size;
}
}
/***************************************************************************
* public FileOutputStream(String filename, boolean append) Creates an
* output file stream to write to the file with the specified name. If the
* second argument is true, then bytes will be written to the end of the
* file rather than the beginning.
*
* If the file exists but is a directory rather than a regular file, does
* not exist but cannot be created, or cannot be opened for any other reason
* then a ?????????????????????????????.
*
* Parameters: file - Directories and files are seperated with "/". Do not
* write the leading "/" in the filename string.
**************************************************************************/
public FileOutputStream(int streamtype, String filename) throws IOException {
this(streamtype, filename, false);
}
/***************************************************************************
* public void close() Closes this file output stream and releases any
* system resources associated with this stream. This file output stream may
* no longer be used for writing bytes.
**************************************************************************/
public void close() {
fatlowlevel.Flush();
}
/***************************************************************************
* public void write(byte[] b) Writes b.length or while (b[i++] != 0) bytes
* from the specified byte array to this file output stream.
*
* Parameters: b - the data.
**************************************************************************/
public void write(byte[] b) throws IOException {
write(b, (int) offset, b.length);
}
/***************************************************************************
* public void write(byte[] b, int off, int len) Writes len bytes from the
* specified byte array starting at offset off to this file output stream.
*
* Overrides: write in class OutputStream Parameters: b - the data. off -
* the start offset in the data. len - the number of bytes to write.
**************************************************************************/
public void write(byte[] b, int off, int len) throws IOException {
int block;
int byte_count;
if (b.length < len) {
len = b.length;
}
if (((offset + (long) (off + len))) > (size + 1)) {
if (((offset + (long) (off + len)) / FatItS.BlockSize) < (size / FatItS.BlockSize)) {
int diff = ((int) (offset + (long) (off + len)) / FatItS.BlockSize) - (int) (size / FatItS.BlockSize);
for (int i = 0; i < diff; i++) {
FatItS.fat_grow_file(fatlowlevel, startcluster);
}
size = offset + (long) (off + len - 1);
entryBuffer = FatItS.fat_mod_file(fatlowlevel, dirCluster, filename, size, attribs, entryBuffer);
}
}
offset = offset + (long) off;
int k = 0;
for (int i = 0; i < ((len / FatItS.BlockSize) + 1); i++) {
block = ((int) offset) / FatItS.BlockSize;
byte_count = ((int) offset) % FatItS.BlockSize;
FatItS.fat_read_file(fatlowlevel, startcluster, buffer, block);
while ((byte_count < 512) && (k < len)) {
buffer[byte_count] = (int) b[k];
k++;
byte_count++;
offset++;
if ((int) size <= (int) offset) {
size++;
}
}
offset--;
FatItS.fat_write_file(fatlowlevel, startcluster, buffer, block);
offset++;
if (size <= offset) {
size++;
if (((offset) % FatItS.BlockSize) == 0) {
FatItS.fat_grow_file(fatlowlevel, startcluster);
}
entryBuffer = FatItS.fat_mod_file(fatlowlevel, dirCluster, filename, size-1, attribs, entryBuffer);
}
if (!(k < len)) {
break;
}
}
}
/***************************************************************************
* public void write(int b) Writes the specified byte to this file output
* stream. Implements the write method of OutputStream.
*
* Parameters: b - the byte to be written.
**************************************************************************/
public void write(int b) throws IOException {
int block;
int byte_count;
block = ((int) offset) / FatItS.BlockSize;
byte_count = ((int) offset) % FatItS.BlockSize;
FatItS.fat_read_file(fatlowlevel, startcluster, buffer, block);
buffer[byte_count] = b;
FatItS.fat_write_file(fatlowlevel, startcluster, buffer, block);
offset++;
if (size <= offset) {
size++;
if (((offset) % FatItS.BlockSize) == 0) {
FatItS.fat_grow_file(fatlowlevel, startcluster);
}
entryBuffer = FatItS.fat_mod_file(fatlowlevel, dirCluster, filename, size-1, attribs, entryBuffer);
}
}
public void delete() {
// TODO implement delete of this file -> call fatits.unlink
}
}