예제 #1
0
파일: fuseLib.c 프로젝트: ferreiro/C
/**
 * @brief Write data on an opened file
 *
 * Help from FUSE
 *
 * Write should return exactly the number of bytes requested except on error.
 * 
 * @param path file path
 * @param buf buffer where we have data to write
 * @param size quantity of bytes to write
 * @param offset offset over the writing
 * @param fi FUSE structure linked to the opened file
 * @return 0 on success and <0 on error
 **/
static int my_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
	char buffer[BLOCK_SIZE_BYTES]; // 1 bloque de caracteres.
	int bytes2Write = size, totalWrite = 0;
	NodeStruct *node = myFileSystem.nodes[fi->fh]; // fh==File handle. May be filled in by filesystem in open().

	fprintf(stderr, "--->>>my_write: path %s, size %zu, offset %jd, fh %"PRIu64"\n", path, size, (intmax_t)offset, fi->fh);

	// Increase the file size if it is needed
	if(resizeNode(fi->fh, size + offset) < 0)
		return -EIO;

	// Write data
	while(bytes2Write) {
		int i;
		int currentBlock, offBloque;
		currentBlock = node->blocks[offset / BLOCK_SIZE_BYTES];
		offBloque = offset % BLOCK_SIZE_BYTES;
	
		// posicionas el cursor del archivo en el bloque + offset.
		// lees un bloque entero empezando en esa posición. SI alguno de los dos falla exit.
		if((lseek(myFileSystem.fdVirtualDisk, currentBlock * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
		        (read(myFileSystem.fdVirtualDisk, &buffer, BLOCK_SIZE_BYTES) == -1)) {
			perror("Failed lseek/read in my_write");
			return -EIO;
		}
		
		// Desde el punto inicial del offset, hasta el final del bloque, escribes la información
		// del buf (texto que nos pasan en la función) en el buffer.
		for(i = offBloque; (i < BLOCK_SIZE_BYTES) && (totalWrite < size); i++) {
			buffer[i] = buf[totalWrite++];
		}
		
		// GUardas el buffer con la información modificada en el archivo indicado en el descriptor físico.
		if((lseek(myFileSystem.fdVirtualDisk, currentBlock * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
		        (write(myFileSystem.fdVirtualDisk, &buffer, BLOCK_SIZE_BYTES) == -1)) {
			perror("Failed lseek/write in my_write");
			return -EIO;
		}

		// Discont the written stuff
		bytes2Write -= (i - offBloque);
		offset += i;
	}
	sync();
	
	node->modificationTime = time(NULL);
	updateSuperBlock(&myFileSystem);
	updateBitmap(&myFileSystem);
	updateNode(&myFileSystem, fi->fh, node);

	return size;
}
예제 #2
0
파일: fuseLib.c 프로젝트: ferreiro/C
int my_unlink(const char *filename) {
	
	
	// printDirectory(myFileSystem.directory); // DEBUG stuff only for debugging
	
	/***** Copiar filename sin '/' en una nueva variable para 
	 ***** poder pasarla a findFileByNAme (que no admite strings constantes) ****/
	
	int i=0;
	char* fname=(char*)(filename+1); // Convert ffrom const char to char. Y también, quitar el primer character (/) sumando uno al puntero de filename (hace algoritimia de punteros.)
		
	
	/** 1. Buscar si el archivo está en nuestro directorio **/
	/** Si está, liberar el archivo y poner el nombre a empty **/
	/** OJO! NO hay que tocar nodeIdx... **/
	
	int nodeIndexDir = findFileByName(&myFileSystem, fname); // NodeIDx índice que ocupa un nodo en el array de nodos
	 
	if (nodeIndexDir == -1) {
		fprintf(stderr, "File wasn't found on the directory entry\n");  
		return -1; // File is not on the directory.
	}
	
	// FILE to erase is on the directory. Free the directory entry.
	
	myFileSystem.directory.numFiles -= 1; // Decrementar numero de archivos en el directorio.
	myFileSystem.directory.files[nodeIndexDir].freeFile = true; // Put the node in directory as free.
	updateDirectory(&myFileSystem);
	
	int nodeIdx = myFileSystem.directory.files[nodeIndexDir].nodeIdx; // Hacer una copia de nodoIDx del directorio que nos sirve para acceder al array de nodos.
	NodeStruct* inode=myFileSystem.nodes[nodeIdx];
	
	/** 2. Borrar datos y liberar nodo usando el nodeIdx obtenido del directorio **/

	myFileSystem.numFreeNodes += 1; // Increase the number of free nodes by 1 because e erased one.
	
	for (i=0;i<inode->numBlocks;i++)
		myFileSystem.bitMap[inode->blocks[i]] = 0; // Marcar bloques de datos en bitmap como libre
 
	myFileSystem.superBlock.numOfFreeBlocks+=inode->numBlocks;
	updateBitmap(&myFileSystem);
	updateSuperBlock(&myFileSystem);
		
 	/**********************************************
 	 * 	Se podría poner unicamente a NULL? Es peor?
 	 **********************************************/
 	 
	inode->numBlocks=0;
	inode->fileSize=0;
	inode->freeNode=true; // Delete the note from the node's array.

	updateNode(&myFileSystem,nodeIdx,inode);
	
	free(inode);
	myFileSystem.nodes[nodeIdx]=NULL;
	
 	  
 	//printAllNodes(myFileSystem.nodes);
 	//printDirectory(myFileSystem.directory); // DEBUG stuff only for debugging

	fprintf(stderr, "\n Congrats!!! %s file deleted \n", filename);
 	
	return 0;
}
예제 #3
0
파일: fuseLib.c 프로젝트: ferreiro/C
/**
 * @brief Modifies the data size originally reserved by an inode, reserving or removing space if needed.
 *
 * @param idxNode inode number
 * @param newSize new size for the inode
 * @return int
 **/
int resizeNode(uint64_t idxNode, size_t newSize) {
	NodeStruct *node = myFileSystem.nodes[idxNode];
	char block[BLOCK_SIZE_BYTES];
	int i, diff = newSize - node->fileSize;

	if(!diff)
		return 0;

	memset(block, 0, sizeof(char)*BLOCK_SIZE_BYTES);

	/// File size increases
	if(diff > 0) {

		/// Delete the extra conent of the last block if it exists and is not full
		if(node->numBlocks && node->fileSize % BLOCK_SIZE_BYTES) {
			int currentBlock = node->blocks[node->numBlocks - 1];
			if((lseek(myFileSystem.fdVirtualDisk, currentBlock * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
			        (read(myFileSystem.fdVirtualDisk, &block, BLOCK_SIZE_BYTES) == -1)) {
				perror("Failed lseek/read in resizeNode");
				return -EIO;
			}
			int offBlock = node->fileSize % BLOCK_SIZE_BYTES;
			int bytes2Write = (diff > (BLOCK_SIZE_BYTES - offBlock)) ? BLOCK_SIZE_BYTES - offBlock : diff;
			for(i = 0; i < bytes2Write; i++) {
				block[offBlock++] = 0;
			}

			if((lseek(myFileSystem.fdVirtualDisk, currentBlock * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
			        (write(myFileSystem.fdVirtualDisk, &block, BLOCK_SIZE_BYTES) == -1)) {
				perror("Failed lseek/write in resizeNode");
				return -EIO;
			}
		}

		/// File size in blocks after the increment
		int newBlocks = (newSize + BLOCK_SIZE_BYTES - 1) / BLOCK_SIZE_BYTES - node->numBlocks;
		if(newBlocks) {
			memset(block, 0, sizeof(char)*BLOCK_SIZE_BYTES);

			// We check that there is enough space
			if(newBlocks > myFileSystem.superBlock.numOfFreeBlocks)
				return -ENOSPC;

			myFileSystem.superBlock.numOfFreeBlocks -= newBlocks;
			int currentBlock = node->numBlocks;
			node->numBlocks += newBlocks;

			for(i = 0; currentBlock != node->numBlocks; i++) {
				if(myFileSystem.bitMap[i] == 0) {
					myFileSystem.bitMap[i] = 1;
					node->blocks[currentBlock] = i;
					currentBlock++;
					// Clean disk (necessary for truncate)
					if((lseek(myFileSystem.fdVirtualDisk, i * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
					        (write(myFileSystem.fdVirtualDisk, &block, BLOCK_SIZE_BYTES) == -1)) {
						perror("Failed lseek/write in resizeNode");
						return -EIO;
					}
				}
			}
		}
		node->fileSize += diff;

	}
	/// File decreases
	else {
		// File size in blocks after truncation
		int numBlocks = (newSize + BLOCK_SIZE_BYTES - 1) / BLOCK_SIZE_BYTES;
		myFileSystem.superBlock.numOfFreeBlocks += (node->numBlocks - numBlocks);

		for(i = node->numBlocks; i > numBlocks; i--) {
			int nBloque = node->blocks[i - 1];
			myFileSystem.bitMap[nBloque] = 0;
			// Clean disk (it is not really necessary)
			if((lseek(myFileSystem.fdVirtualDisk, nBloque * BLOCK_SIZE_BYTES, SEEK_SET) == (off_t) - 1) ||
			        (write(myFileSystem.fdVirtualDisk, &block, BLOCK_SIZE_BYTES) == -1)) {
				perror("Failed lseek/write in resizeNode");
				return -EIO;
			}
		}
		node->numBlocks = numBlocks;
		node->fileSize += diff;
	}
	node->modificationTime = time(NULL);

	sync();
	
	/// Update all the information in the backup file
	updateSuperBlock(&myFileSystem);
	updateBitmap(&myFileSystem);
	updateNode(&myFileSystem, idxNode, node);

	return 0;
}
예제 #4
0
int myMkfs(MyFileSystem *myFileSystem, int diskSize, char *backupFileName) {
	// We create the virtual disk:
	myFileSystem->fdVirtualDisk = open(backupFileName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

	// Some minimal checks:
	assert(sizeof(SuperBlockStruct) <= BLOCK_SIZE_BYTES);
	assert(sizeof(DirectoryStruct) <= BLOCK_SIZE_BYTES);
	int numBlocks = diskSize / BLOCK_SIZE_BYTES;
	int minNumBlocks = 3 + MAX_BLOCKS_WITH_NODES + 1;
	// 3 --> por el superbloque, el raiz y el mapa de bits.
	// 1 --> porque al menos tenemos un bloque para datos.
	int maxNumBlocks = NUM_BITS;
	if(numBlocks < minNumBlocks) {
		return -1;
	}
	if(numBlocks >= maxNumBlocks) {
		return -2;
	}

	/// BITMAP
	// Initialization
	int i;
	for(i = 0; i < NUM_BITS; i++) {
		myFileSystem->bitMap[i] = 0;
	}

	// First three blocks will be superblock, bitmap and directory
	myFileSystem->bitMap[BITMAP_IDX] = 1;
	myFileSystem->bitMap[SUPERBLOCK_IDX] = 1;
	myFileSystem->bitMap[DIRECTORY_IDX] = 1;
	// Next MAX_BLOCKS_WITH_NODES will contain inodes
	for(i = 3; i < 3 + MAX_BLOCKS_WITH_NODES; i++) {
		myFileSystem->bitMap[i] = 1;
	}
	updateBitmap(myFileSystem);

	/// DIRECTORY
	// Initialization
	myFileSystem->directory.numFiles = 0;
	for(i = 0; i < MAX_FILES_PER_DIRECTORY; i++) {
		myFileSystem->directory.files[i].freeFile = 1;
	}
	updateDirectory(myFileSystem);

	/// INODES
	NodeStruct currentNode;
	currentNode.freeNode = 1;
	for(i = 0; i < MAX_NODES; i++) {
		updateNode(myFileSystem, i, &currentNode);
	}

	/// SUPERBLOCK
	initializeSuperBlock(myFileSystem, diskSize);
	updateSuperBlock(myFileSystem);
	sync();

	// At the end we have at least one block
	assert(myQuota(myFileSystem) >= 1);

	if(initializeNodes(myFileSystem)){
		myFree(myFileSystem);
		return -3;
	}

	printf("SF: %s, %d B (%d B/block), %d blocks\n", backupFileName, diskSize, BLOCK_SIZE_BYTES, numBlocks);
	printf("1 block for SUPERBLOCK (%u B)\n", (unsigned int)sizeof(SuperBlockStruct));
	printf("1 block for BITMAP, covering %u blocks, %u B\n", (unsigned int)NUM_BITS, (unsigned int)(NUM_BITS * BLOCK_SIZE_BYTES));
	printf("1 block for DIRECTORY (%u B)\n", (unsigned int)sizeof(DirectoryStruct));
	printf("%d blocks for inodes (%u B/inode, %u inodes)\n", MAX_BLOCKS_WITH_NODES, (unsigned int)sizeof(NodeStruct), (unsigned int)MAX_NODES);
	printf("%d blocks for data (%d B)\n", myFileSystem->superBlock.numOfFreeBlocks, BLOCK_SIZE_BYTES * myFileSystem->superBlock.numOfFreeBlocks);
	printf("Formatting completed!\n");

	return 0;
}