Esempio n. 1
0
int fat_open(struct inode* inode) {
	fat_t* fat = (fat_t*) inode->userdata;
	if(unlikely(!fat)) {
		errno = EINVAL;
		return E_ERR;
	}	


	if(fat->entry_sector == 0)
		return E_OK;


	fat->dev->position = fat->entry_sector * fat->bytes_per_sector;
	inode_t* child = NULL;


	
	static char buf[512];
	fat_entry_t* e = (fat_entry_t*) &buf;
	fat_entry_lfn_t* lfn = (fat_entry_lfn_t*) &buf;

	int entry = 0;

	do {

		if(unlikely(fat_check_entry(fat, &entry) == E_ERR))
			break;

		if(vfs_read(fat->dev, &buf, 32) != 32) {
			errno = EIO;
			return E_ERR;
		}


		if(e->name[0] == '\0')
			break;

		child = (inode_t*) kmalloc(sizeof(inode_t), GFP_ATOMIC);
		if(unlikely(!child)) {
			errno = ENOMEM;
			return E_ERR;
		}

		memset(child, 0, sizeof(inode_t));



		child->name = (const char*) kmalloc(FAT_MAXFN, GFP_ATOMIC);
		if(unlikely(!child->name)) {
			kfree((void*) child);

			errno = ENOMEM;
			return E_ERR;
		}

		memset((void*) child->name, 0, FAT_MAXFN);




		if(e->flags == ATTR_LFN) {
			do {
#if CONFIG_LFN
				lfncat(child->name, lfn->name_2, 2);
				lfncat(child->name, lfn->name_1, 6);
				lfncat(child->name, lfn->name_0, 5);
#endif

				if(unlikely(fat_check_entry(fat, &entry) == E_ERR)) {
					kfree((void*) child->name);
					kfree((void*) child);

					errno = ENOENT;
					return E_ERR;
				}

				if(vfs_read(fat->dev, &buf, 32) != 32) {
					kfree((void*) child->name);
					kfree((void*) child);

					errno = EIO;
					return E_ERR;
				}
			} while(lfn->flags == ATTR_LFN);
		}


		if(e->name[0] == '\xE5') {				
			kfree((void*) child->name);
			kfree((void*) child);

			continue;
		}

		if(child->name[0] == '\0')
			fatcat(child->name, e->name, e->extension);
		

		struct inode_childs* cx;
		for(cx = inode->childs; cx; cx = cx->next) {
			if(strcmp(cx->inode->name, child->name) == 0) {
				kfree((void*) child->name);
				kfree((void*) child);

				continue;
			}
		}


		fat_t* fc = (fat_t*) kmalloc(sizeof(fat_t), GFP_USER);
		if(unlikely(!fc)) {
			kfree((void*) child->name);
			kfree((void*) child);

			errno = ENOMEM;
			return E_ERR;
		}

		memcpy(fc, fat, sizeof(fat_t));

		int cluster = (e->cluster_high << 16) | (e->cluster_low & 0xFFFF);
		fc->entry_sector = cluster
					? CLUSTER_TO_SECTOR(fc, cluster) 
					: 0
					;


		child->userdata = (void*) fc;

		child->ino = vfs_inode();
		child->mode = (e->flags & ATTR_DIRECTORY ? S_IFDIR : S_IFREG) |
				(e->flags & ATTR_RDONLY ? 0444 : 0666) & ~current_task->umask;

		child->dev =
		child->rdev =
		child->nlink = 0;

		child->uid = current_task->uid;
		child->gid = current_task->gid;
		child->size = (off64_t) e->size;

		child->atime = 
		child->ctime = 
		child->mtime = timer_gettime();
	
		child->parent = inode;
		child->link = NULL;

		child->childs = NULL;


		if(e->flags & ATTR_DIRECTORY) {
			child->finddir = fat_finddir;
			child->mknod = fat_mknod;
			child->rename = NULL;
			child->unlink = fat_unlink;
			child->open = fat_open;
			child->close = fat_close;
		} else {
			child->read = NULL;
			child->write = NULL;
		}
		
		child->chown = NULL;
		child->chmod = NULL;
		child->ioctl = NULL;
		


		

		cx = (struct inode_childs*) kmalloc(sizeof(struct inode_childs), GFP_KERNEL);
		cx->inode = child;
		cx->next = inode->childs;
		inode->childs = cx;
				
	} while(1);
}
Esempio n. 2
0
struct inode* iso9660_finddir(struct inode* inode, char* name) {
	if(unlikely(!inode)) {
		errno = EINVAL;
		return NULL;
	}

	if(unlikely(!inode->userdata)) {
		errno = EINVAL;
		return NULL;
	}

	iso9660_t* ctx = (iso9660_t*) inode->userdata;
	KASSERT(ctx);


	iso9660_dir_t* nodes = (iso9660_dir_t*) kmalloc(iso9660_getlsb32(ctx->dir.length), GFP_USER);
	iso9660_dir_t* snodes = nodes;		
	KASSERT(nodes);

	

	ctx->dev->position = iso9660_getlsb32(ctx->dir.lba) * ISO9660_SECTOR_SIZE;
	if(unlikely(vfs_read(ctx->dev, nodes, iso9660_getlsb32(ctx->dir.length)) != iso9660_getlsb32(ctx->dir.length))) {
		kfree(nodes);

		errno = EIO;
		return NULL;
	}


	
	/* Skip dots (".", "..") */
	nodes = (iso9660_dir_t*) ((uintptr_t) nodes + nodes->size);
	nodes = (iso9660_dir_t*) ((uintptr_t) nodes + nodes->size);

	int i;
	for(i = 0; i < iso9660_getlsb32(ctx->dir.length); i += ISO9660_SECTOR_SIZE) {
		if(i != 0)
			nodes = (iso9660_dir_t*) ((uintptr_t) snodes + i);
		
		for(
			; 
			nodes->size;
			nodes = (iso9660_dir_t*) ((uintptr_t) nodes + nodes->size)
		) {

			inode_t* child = (inode_t*) kmalloc(sizeof(inode_t), GFP_ATOMIC);
			if(unlikely(!child)) {
				errno = ENOMEM;
				return NULL;
			}

			memset(child, 0, sizeof(inode_t));




#if HAVE_ROCKRIDGE
			register int len = nodes->idlen;
			if(!(len & 1))
				len++;
			
			void* rockridge_offset = (void*) ((uintptr_t) &nodes->reserved + len);
#endif	


#if HAVE_ROCKRIDGE			
			child->name = rockridge_getname(rockridge_offset);
#else

			child->name = (const char*) kmalloc(nodes->idlen + 1, GFP_USER);
			KASSERT(child->name);
			
			memset((void*) child->name, 0, nodes->idlen + 1);
			strncpy((char*) child->name, nodes->reserved, nodes->idlen);
			
			iso9660_checkname((char*) child->name);
#endif

			if(strcmp(child->name, name) != 0) {
				kfree((void*) child->name);
				kfree((void*) child);

				continue;
			}
		

			
			child->ino = vfs_inode();
			child->mode = (nodes->flags & ISO9660_FLAGS_DIRECTORY ? S_IFDIR : S_IFREG) | 0666 & ~current_task->umask;

			child->dev =
			child->rdev =
			child->nlink = 0;

			child->uid = current_task->uid;
			child->gid = current_task->gid;
			child->size = (off64_t) iso9660_getlsb32(nodes->length);


			child->atime = 
			child->ctime = 
			child->mtime = timer_gettime();
		
			child->parent = inode;
			child->link = NULL;

			child->childs = NULL;


			if(nodes->flags & ISO9660_FLAGS_DIRECTORY) {
				child->open = iso9660_open;
				child->close = iso9660_close;
				child->finddir = iso9660_finddir;
				child->unlink = iso9660_unlink;
			} else {
				child->read = iso9660_read;
				child->write = NULL;
			}
			
			child->chown = NULL;
			child->chmod = NULL;
			child->ioctl = NULL;

#if HAVE_ROCKRIDGE
			rockridge_getmode(rockridge_offset, &child->mode,
												&child->uid,
												&child->gid,
												&child->nlink);
#endif			

			iso9660_t* cctx = (iso9660_t*) kmalloc(sizeof(iso9660_t), GFP_USER);
			KASSERT(cctx);

			memcpy(cctx, ctx, sizeof(iso9660_t));
			memcpy(&cctx->dir, nodes, sizeof(iso9660_dir_t));

			child->userdata = (void*) cctx;



			

			struct inode_childs* cx = (struct inode_childs*) kmalloc(sizeof(struct inode_childs), GFP_KERNEL);
			cx->inode = child;
			cx->next = inode->childs;
			inode->childs = cx;

			return child;
		}
	}

	kfree(snodes);

	errno = ENOENT;
	return NULL;
}