Esempio n. 1
0
/* We will search the inode that belongs to this name, currently by a
   complete linear search through the inodes belonging to this
   filesystem. This has to be fixed. */
static struct smb_inode_info *
smb_find_dir_inode(struct inode *parent, const char *name, int len)
{
	struct smb_server *server = SMB_SERVER(parent);
	struct smb_inode_info *dir = SMB_INOP(parent);
	struct smb_inode_info *result = &(server->root);

	if (name == NULL)
	{
		return NULL;
	}
	if ((len == 1) && (name[0] == '.'))
	{
		return dir;
	}
	if ((len == 2) && (name[0] == '.') && (name[1] == '.'))
	{
		return dir->dir;
	}
	do
	{
		if (result->dir == dir)
		{
			if (compare_filename(server, name, len,
					     &(result->finfo)) == 0)
			{
				return result;
			}
		}
		result = result->next;
	}
	while (result != &(server->root));

	return NULL;
}
Esempio n. 2
0
static int
smb_lookup(struct inode *dir, const char *name, int len,
	   struct inode **result)
{
	struct smb_dirent finfo;
	struct smb_inode_info *result_info;
	int error;
	int found_in_cache;

	struct smb_inode_info *new_inode_info = NULL;

	*result = NULL;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		printk("smb_lookup: inode is NULL or not a directory.\n");
		iput(dir);
		return -ENOENT;
	}
	DDPRINTK("smb_lookup: %s\n", name);

	/* Fast cheat for . */
	if (len == 0 || (len == 1 && name[0] == '.'))
	{
		*result = dir;
		return 0;
	}
	/* ..and for .. */
	if (len == 2 && name[0] == '.' && name[1] == '.')
	{
		struct smb_inode_info *parent = SMB_INOP(dir)->dir;

		if (parent->state == SMB_INODE_CACHED)
		{
			parent->state = SMB_INODE_LOOKED_UP;
		}
		*result = iget(dir->i_sb, smb_info_ino(parent));
		iput(dir);
		if (*result == 0)
		{
			return -EACCES;
		}
		return 0;
	}
	result_info = smb_find_dir_inode(dir, name, len);

      in_tree:
	if (result_info != NULL)
	{
		if (result_info->state == SMB_INODE_CACHED)
		{
			result_info->state = SMB_INODE_LOOKED_UP;
		}
		*result = iget(dir->i_sb, smb_info_ino(result_info));
		iput(dir);

		if (new_inode_info != NULL)
		{
			smb_kfree_s(new_inode_info,
				    sizeof(struct smb_inode_info));
		}
		if (*result == NULL)
		{
			return -EACCES;
		}
		return 0;
	}
	/* If the file is in the dir cache, we do not have to ask the
	   server. */
	found_in_cache = 0;

	if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0))
	{
		int first = c_last_returned_index;
		int i;

		i = first;
		do
		{
			if (compare_filename(SMB_SERVER(dir), name, len,
					     &(c_entry[i])) == 0)
			{
				finfo = c_entry[i];
				found_in_cache = 1;
				break;
			}
			i = (i + 1) % c_size;
		}
		while (i != first);
	}
	if (found_in_cache == 0)
	{
		DPRINTK("smb_lookup: not found in cache: %s\n", name);
		if (len > SMB_MAXNAMELEN)
		{
			iput(dir);
			return -ENAMETOOLONG;
		}
		error = smb_proc_getattr(dir, name, len, &finfo);
		if (error < 0)
		{
			iput(dir);
			return error;
		}
		finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
	}
	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
				     GFP_KERNEL);

	/* Here somebody else might have inserted the inode */

	result_info = smb_find_dir_inode(dir, name, len);
	if (result_info != NULL)
	{
		goto in_tree;
	}

	if (new_inode_info == NULL)
	{
		iput(dir);
		return -ENOMEM;
	}
	new_inode_info->finfo = finfo;

	DPRINTK("attr: %x\n", finfo.attr);

	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
	{
		iput(dir);
		return -EACCES;
	}
	DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info);
	iput(dir);
	return 0;
}
Esempio n. 3
0
//returns sector number where directory is located, negative = error
int dir_lookup(char* path)
{
	char dname[MAX_PATH_LEN+1];
	dname[MAX_PATH_LEN] = '\0';
	strncpy(dname, path, MAX_PATH_LEN);
	char* dname_part = NULL;
	dname_part = strtok(dname, "/");
	int dlocation = start_of_root_dir();
	//special case for root directory
	char root_dir_dname[] = ".";
	if(strcmp(path, root_dir_dname) == 0)
	{
		return start_of_root_dir();
	}
	bool found = false;
	//traverse the directory structure
	while(dname_part != NULL)
	{
		found = false;
		debug_printf("looking for directory %s\n", dname_part);
		// printf("	====looking for directory %s\n", dname_part);
		// printf("	dir_entries_sector() = %d \n",dir_entries_sector());
		while(!found)
		{
			//read sector into a memory block
			uint8_t dir_sector[bytes_sector()];
			read_block(dlocation, &dir_sector);
			fat_file_t dir_files[dir_entries_sector()];
			

			memcpy(&dir_files, &dir_sector, (size_t)bytes_sector());
			//search the memory block for matching name
			for(int i = 0; i < dir_entries_sector(); ++i)
			{
				if(dir_files[i].name[0] == 0x00)
				{
					//not found, don't need to keep looking
					// printf("	//not found, don't need to keep looking");

					break;
				}
				else if(dir_files[i].name[0] == deleted_file)
				{
					//deleted
					continue;
				}
				else if(is_lfn(dir_files[i].attr))
				{
					//LFN entry
					continue;
				}
				else if(dir_files[i].attr.vol == 1 ||
					dir_files[i].attr.dir == 0 ||
					dir_files[i].attr.device == 1)
				{
					//volume label, not a directory, device file
					continue;
				}
				if(compare_filename(dname_part, dir_files[i]) == 0)
				{
					//got a directory with the correct name
					dlocation = data_cluster_to_sector(dir_files[i].first_cluster);
					// printf("	dir_files[i].first_cluster: %d \n", dir_files[i].first_cluster);
					found = true;
					break;
				}
			}
			if(found)
			{
				break;
			}
			//directory not found yet, need to pick the next sector to search
			//(if available)
			if(dlocation < start_of_data())
			{
				if(dlocation < start_of_root_dir() + root_dir_sectors())
				{
					//there are more root directory sectors to search
					dlocation++;
				}
				else
				{
					//directory doesn't exist
					return -1;
				}
			}
			else
			{
				if((dlocation + 1 - start_of_data()) % sectors_cluster() != 0)
				{
					//more sectors in this cluster
					dlocation++;
				}
				else if(next_cluster_for_sector(dlocation) <= max_cluster)
				{
					//continues into another cluster
					uint16_t next_c = next_cluster_for_sector(dlocation);
					dlocation = data_cluster_to_sector(next_c);
				}
				else
				{
					//directory doesn't exist
					return -1;
				}
			}
		}
		// printf("	dlocation: %d \n", dlocation);

		dname_part = strtok(NULL, "/");
	}
	return dlocation;
}
Esempio n. 4
0
//returns file entry number in directory or -1 for not found
int file_lookup(char* name, int *directory_sector)
{
	int dlocation = *directory_sector;
	bool root_dir = true;
	if(dlocation >= start_of_data())
	{
		root_dir = false;
	}
	debug_printf("looking for file %s\n", name);
	while(true)
	{
		uint8_t dir_sector[bytes_sector()];
		read_block(dlocation, &dir_sector);
		fat_file_t dir_files[dir_entries_sector()];
		memcpy(&dir_files, &dir_sector, (size_t)bytes_sector());
		//search the memory block for matching name
		for(int i = 0; i < dir_entries_sector(); ++i)
		{
			if(dir_files[i].name[0] == 0x00)
			{
				//not found, don't need to keep looking
				break;
			}
			else if(dir_files[i].name[0] == deleted_file)
			{
				//deleted
				continue;
			}
			else if(is_lfn(dir_files[i].attr))
			{
				//LFN entry
				continue;
			}
			else if(dir_files[i].attr.vol == 1 ||
				dir_files[i].attr.device == 1)
			{
				//volume label, device file
				continue;
			}
			if(compare_filename(name, dir_files[i]) == 0)
			{
				//got a directory with the correct name
				*directory_sector = dlocation;
				return i;
			}
		}
		//file not found yet, need to pick the next sector to search
		//if there is actually a next sector
		if(root_dir)
		{
			if(dlocation < start_of_root_dir() + root_dir_sectors())
			{
				//there are more root directory sectors to search
				dlocation++;
			}
			else
			{
				//file doesn't exist
				return -1;
			}
		}
		else
		{
			if((dlocation + 1 - start_of_data()) % sectors_cluster() != 0)
			{
				//more sectors to search in this cluster
				dlocation++;
			}
			else if(next_cluster_for_sector(dlocation) <= max_cluster)
			{
				//continues into another cluster
				uint16_t next_c = next_cluster_for_sector(dlocation);
				dlocation = data_cluster_to_sector(next_c);
			}
			else
			{
				return -1;
			}
		}
	}
	return -1;
}
Esempio n. 5
0
/* Known issue: central dir must be < BUFSIZE bytes */
static int find_matching_cd_entry (FILE *fp, char *match,
	t_end_of_cent_dir *ecd, t_central_dir_ent *cd)
{
	int		i, j, found = 0, err;
	int	count, read;
	char 	*p;

	/* we'll read the entire central directory or BUFSIZE bytes, whichever is smaller */
	if (ecd->size_of_cent_dir > BUFSIZE)
		count = BUFSIZE;
	else
		count = ecd->size_of_cent_dir;

	/* read from start of central directory */
	err = fseek (fp, ecd->offset_to_start_of_cent_dir, SEEK_SET);
	if (err==0)
	{
		read = fread (input_buffer, 1, count, fp);
		if (read!=count)
		{
			ERRORMSG ("Error in zipfile: couldn't read %d bytes from central directory\n", count);
			err = -1;
		}
	}
	else
		ERRORMSG ("Error in zipfile: couldn't fseek to start of central directory\n");

	if (err==0)
	{
		/* loop through entries in central directory for suitable match */
		for (i=0, p=input_buffer; found==0 && i<ecd->total_entries_cent_dir; i++)
		{
			char filename[256];

			read_central_dir_entry (p, cd);

			/* copy filename and force to upper case */
			for (j=0; j<cd->filename_length && j<254; j++)
				filename[j] = toupper (cd->filename[j]);
			filename[j] = '\0';

			/* compare filename */
			if (!compare_filename (filename, match))
			{
				found = 1;

				/* check for suitability */
				if (cd->compression_method != 0x0000 &&
					cd->compression_method != 0x0008 )
				{
					found = 0;
					ERRORMSG ("Error in zipfile: compression method for file %s unsupported.\n",
						match);
					ERRORMSG ("Method: $%04x  must be $0000 (Stored) or $0008 (Deflated)\n",
						cd->compression_method);
				}
				if	(cd->version_needed_to_extract > 0x14)
				{
					found = 0;
					ERRORMSG ("Error in zipfile: version for file %s too new.\n", match);
					ERRORMSG ("Version: $%02x must be $14 or less\n",
						cd->version_needed_to_extract);
				}
				if (cd->os_needed_to_extract != 0x00)
				{
					found = 0;
					ERRORMSG ("Error in zipfile: OS for file %s not supported.\n",
						match);
					ERRORMSG ("OS: $%02x must be $00\n",cd->os_needed_to_extract);
				}
				if (cd->disk_number_start != ecd->number_of_this_disk)
				{
					found = 0;
					ERRORMSG ("Error in zipfile: zipfile cannot span disks\n");
				}
			}

			/* skip to next entry in central dir */
			p += ZIPCFN + cd->filename_length + cd->extra_field_length
				+ cd->file_comment_length;
		}
	}

	if (!found) err = -1;
	return err;
}