int isofs_open(const char *path)
{
	struct iso_inode *inode = isofs_lookup(path);
	if(!inode) {
		fprintf(stderr,"no such file or directory found \n");
		return -ENOENT;
	}
	if(ISO_FLAGS_DIR(inode->record->flags)) {
		fprintf(stderr,"not a regular file may be a directory\n");
		return -EINVAL;
	}
	return 0;
}
int isofs_read(const char *path,char *read_buf,size_t size,off_t offset)
{
	log_msg("i am now in read_block\n");
	struct iso_inode *inode = isofs_lookup(path);
	if(!inode) {
		fprintf(stderr,"no such file or directory found \n");
		return -ENOENT;
	}
	if(ISO_FLAGS_DIR(inode->record->flags)) {
		fprintf(stderr,"not a regular file may be a directory\n");
		return -EINVAL;
	}
	int data_size = gvar->data_size;
	struct iso_directory_record *dr = inode->record;
	int start_block = isonum_733(dr->extent);
	int end_block = isonum_733(dr->size)/data_size;
	int in_block = end_block - start_block ;
	
	int offset_block_start = offset / data_size;
	int offset_block_end = (offset + size) / data_size;
	int offset_shift_point = (offset%data_size);
	int block = offset_block_start + start_block;
	log_msg("malloced .....\n");
	char *buf = (char *) malloc(data_size);
	if(!buf) {
		perror("isofs_read:cannot malloc");
		exit(0);
	}
	int total = 0;
	int count = 0;
	int len;
	do{
		log_msg("read_raw_block.....\n");
		len = read_raw_block(block,buf);
		log_msg("buffer is now ....%s\n",buf);
		memcpy(read_buf+count*data_size,buf+offset_shift_point,data_size);
		log_msg("the read_buf is %s",read_buf);
		offset_shift_point = 0;
		count ++;
		block++;
		total += len;
	}while(count <= in_block);
	
	return total;
}
예제 #3
0
int fs_real_open(const char *path)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("path=%s",path);

    isofs_inode *inode = fs_lookup(path);
    if (inode == NULL)
    {
        struct stat v_stbuf;

        if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
        {
            if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
            return 0;
        }

        if (data->union_mounting && stat(path,&v_stbuf)==0)
        {
            if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
            return 0;
        }

        FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }
    if (ISO_FLAGS_DIR(inode->record->flags))
    {
        FSDEBUG("%s not a file",path);
        return -EINVAL;
    }
    if (ISO_FLAGS_HIDDEN(inode->record->flags))
    {
        FSDEBUG("%s is a hidden file",path);
        // return -EPERM;
    }
    return 0;
}
예제 #4
0
int fs_real_opendir(const char *path)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("path=%s", path);

    isofs_inode *inode = fs_lookup(path);
    if (inode==NULL)
    {
        struct stat v_stbuf;

        if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
        {
            if (!S_ISDIR(v_stbuf.st_mode)) return -ENOENT;
            return 0;
        }

        if (data->union_mounting && lstat(path,&v_stbuf)==0)
        {
            if (!S_ISDIR(v_stbuf.st_mode)) return -ENOENT;
            return 0;
        }

        FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }

    if (!ISO_FLAGS_DIR(inode->record->flags))
    {
        FSDEBUG("%s not a dir",path);
        return -ENOTDIR;
    }

    return 0;
}
예제 #5
0
int fs_real_read(const char *path, char *out_buf, size_t size, off_t offset)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("path=%s",path);

    isofs_inode *inode = fs_lookup(path);
    if (inode == NULL)
    {
        struct stat v_stbuf;
        int v_file;
	ssize_t v_count;

        // Use our own loader
        if (data->glibc && strcmp(path,"/lib/ld-linux.so.2")==0)
        {
            v_file = open("/lib/ld-klik2.so.2", O_RDONLY);
            if (v_file == -1) return -EACCES;
            lseek(v_file, offset, SEEK_SET);
            v_count = read(v_file, out_buf, size);
            close(v_file);
            return v_count;
        }

        if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
        {
            if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
            v_file = open(newpath, O_RDONLY);
            if (v_file == -1) return -EACCES;
            lseek(v_file, offset, SEEK_SET);
            v_count = read(v_file, out_buf, size);
            close(v_file);
            if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC)
            {
                fs_rewrite_loader(out_buf, v_count);
            }
            return v_count;
        }

        if (data->union_mounting && stat(path,&v_stbuf)==0)
        {
            if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
            v_file = open(path, O_RDONLY);
            if (v_file == -1) return -EACCES;
            lseek(v_file, offset, SEEK_SET);
            v_count = read(v_file, out_buf, size);
            close(v_file);
            if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC)
            {
                fs_rewrite_loader(out_buf, v_count);
            }
            return v_count;
        }

        FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }

    struct iso_directory_record *record = inode->record;
    if (ISO_FLAGS_DIR(record->flags))
    {
        FSDEBUG("%s not a file",path);
        return -EISDIR;
    }
    if (ISO_FLAGS_HIDDEN(record->flags))
    {
        FSDEBUG("%s is a hidden file",path);
        // return -EPERM;
    }

    if (inode->ZF)                                                 // this file is compressed, handle it specially
    {
        int v_count = isofs_real_read_zf(inode, out_buf, size, offset);
	if (v_count<0)
		return -EINVAL;

        if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC)
        {
            fs_rewrite_loader(out_buf, v_count);
        }
        return v_count;
    }

    size_t fsize = isonum_733(record->size);
    if (offset + size > fsize)
    {
        size = fsize - offset;
    }
    if (size < 1)
    {
        return 0;
    }

    int start_block = isonum_733(record->extent);
    if (start_block == 0)                                          // empty file
    {
        return 0;
    }

    int start = offset / data->isofs->data_size;
    int end = (offset + size) / data->isofs->data_size;
    int shift = offset % data->isofs->data_size;
    int block = start_block + start;
    //     printf("read: path %s, size %d, offset %d, fsize %d, start %d, end %d, shift %d\n",
    //         path, size, (int) offset, fsize, start, end, shift);

    char *buf = (char *) malloc(data->isofs->data_size);
    if (!buf)
    {
        FSDEBUG("can\'t malloc: %s",strerror(errno));
        return -ENOMEM;
    }

    int i;
    size_t total_size = 0;
    size_t size_left = size;
    int count = 0;

    for (i=start; i<=end; i++)
    {
        int len = isofs_read_raw_block(block, buf, data->isofs);
        if (len < 0)
        {
            free(buf);
            return len;
        }
        //         printf("read: block %d, len %d, size_left %d\n", block, len, size_left);

        if (len > size_left)
        {
            len = size_left;
        }

        total_size += len;

        memcpy(out_buf + count * data->isofs->data_size, buf + shift, len - shift);

        count++;
        shift = 0;
        size_left -= len;
        block++;
    }

    free(buf);
    if (data->glibc && offset==0 && total_size>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC)
    {
        fs_rewrite_loader(out_buf, total_size);
    }
    return total_size;
}
예제 #6
0
int fs_real_readdir(int real, const char *path, void *filler_buf, fs_dir_fill_t filler)
{
    char ppath[FS_MAXPATH];
    char v_chemin[2048];
    char *newpath=ppath;
    struct dirent *v_dirent;
    struct stat v_stbuf;
    int retval1, retval2;
    DIR *v_dir;
    char *buf = NULL;
    fusioniso_data *data=fusioniso_get_data();

    if (path[0] == '\0')
    {
        FSDEBUG("attempt to read empty path name");
        return -EINVAL;
    }

    FSDEBUG("path=%s flag=%d",path,real);

    isofs_inode *current_inode = fs_lookup(path);
    isofs_inode *inode2 = NULL;

    if (!data->union_mounting && current_inode==NULL)
    {
        FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }

    retval2 = fs_home(path,&newpath);
    if (current_inode == NULL)
    {
        if (real && retval2!=1) goto out_readdir;
        if (!real && retval2!=1)
        {
            g_hash_table_insert(data->real_lookup_table, g_strdup(path), "real");
            return 0;
        }
        if (data->union_mounting)
        {
            retval1 = stat(path, &v_stbuf);
            if (real && retval1==0) goto out_readdir;
            if (!real && retval1==0)
            {
                g_hash_table_insert(data->real_lookup_table, g_strdup(path), "real");
                return 0;
            }
        }
        if (!real) FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }

    struct iso_directory_record *current = current_inode->record;
    if (!ISO_FLAGS_DIR(current->flags))
    {
        FSDEBUG("%s not a dir", path);
        return -ENOTDIR;
    }

    size_t current_size = isonum_733(current->size);

    int block = isonum_733(current->extent);
    buf = (char *) malloc(data->isofs->data_size);
    if (!buf)
    {
        FSDEBUG("can\'t malloc: %s",strerror(errno));
        return -ENOMEM;
    }
    int rc;
    // printf("path %s, current_size %d, block %d\n", path, current_size, block);

    size_t total_size = 0;
    int count = 1;
    int block_count = 0;
    off_t boff = 0;

    while (total_size <= current_size - sizeof(struct iso_directory_record))
    {
        rc = isofs_read_raw_block(block, buf, data->isofs);
        if (rc < 0)
        {
            return rc;
        }
        if (rc != data->isofs->data_size)
        {
            // can`t be allowed
            FSDEBUG("can`t read whole block, read only %d bytes, block %d",rc,block);
            free(buf);
            return -EIO;
        }
        block_count++;

        if (boff > 0)
        {
            total_size += (data->isofs->data_size - boff);
            boff = 0;
        }

        while (boff + sizeof(struct iso_directory_record) <= data->isofs->data_size &&
            total_size <= current_size - sizeof(struct iso_directory_record))
        {

            struct iso_directory_record *record = (struct iso_directory_record *) (buf + boff);
            size_t record_length = isonum_711((unsigned char *) record->length);
            size_t name_len = isonum_711(record->name_len);
            size_t pad_len = ((name_len & 1) ? 0 : 1);            // padding byte if name_len is even
            size_t sa_len = record_length - name_len - sizeof(struct iso_directory_record) - pad_len;

            // printf("block %d, boff %d, total_size %d, current_size %d, record length %d, name_len %d, pad_len %d, sa_len %d\n",
            //     block, (int) boff, total_size, current_size, record_length, name_len, pad_len, sa_len);
            if (record_length == 0)
            {
                // possible end of directory or end of block
                total_size += (data->isofs->data_size - boff);
                boff = 0;
                break;
            }
            if (record_length < sizeof(struct iso_directory_record))
            {
                if (count > 2)                                     // check if . and .. is already read
                {
                    // possible end of directory
                    // at least mkisofs does not set iso_directory_record.size correct
                    // (this is much possible it was my fault and misunderstanding -- dmiceman)
                    // but we need to try next block to be sure
                    /// TODO this is not clear: what to do if next block not contain next directory?
                    total_size += (data->isofs->data_size - boff);
                    boff = 0;
                    break;
                }
                else
                {
                    FSDEBUG("directory record length too small: %d",record_length);
                    free(buf);
                    return -EIO;
                }
            }
            if (name_len > NAME_MAX - 1)
            {
                FSDEBUG("file name length too big: %d",name_len);
                free(buf);
                return -EIO;
            }
            if (sa_len < 0)
            {
                // probably something wrong with name_len
                FSDEBUG("wrong name_len in directory entry: %d, record_length %d",name_len,record_length);
                free(buf);
                return -EIO;
            }
            if (count > 2 && name_len == 1 && record->name[0] == 0)
            {
                // looks like this is normal situation to meet another directory because
                // there is no clear way to find directory end
                //                 fprintf(stderr, "readdir: next directory found while processing another directory! boff %d, total_size %d, current_size %d, block %d, count %d\n",
                //                     (int) boff, total_size, current_size, block, count);
                goto out_readdir;
            }

            isofs_inode *inode = (isofs_inode *) malloc(sizeof(isofs_inode));
            if (inode == NULL)
            {
                FSDEBUG("can\'t malloc: %s",strerror(errno));
                return -ENOMEM;
            }
            memset(inode, 0, sizeof(isofs_inode));
            inode->st_ino = data->isofs->last_ino;
            data->isofs->last_ino++;

            struct iso_directory_record *n_rec =
                (struct iso_directory_record *) malloc (sizeof(struct iso_directory_record));
            if (!n_rec)
            {
                FSDEBUG("can\'t malloc: %s",strerror(errno));
                return -ENOMEM;
            }
            memcpy(n_rec, record, sizeof(struct iso_directory_record));
            inode->record = n_rec;

            if (data->isofs->susp || path[1] == '\0')               // if susp is known to be present or this is a root dir ("/")
            {
                /*                printf("sa offset %d, sa_len %d\n",
                                                                        sizeof(struct iso_directory_record) + name_len + pad_len, sa_len);*/
                rc = isofs_parse_sa(inode,
                    ((char *) record) + sizeof(struct iso_directory_record) + name_len + pad_len + data->isofs->susp_skip,
                    sa_len);
                if (rc<0)
                {
                    free(buf);
                    isofs_free_inode(inode);
                    return -EIO;
                }
            }

            char *entry = (char *) malloc(NAME_MAX);
            if (!entry)
            {
                FSDEBUG("can\'t malloc: %s",strerror(errno));
                return -ENOMEM;
            }
            if (count == 1)                                        // . entry ('\0' on disk)
            {
                strcpy(entry, ".");
            }                                                     // .. entry ('\1' on disk)
            else if (count == 2)
            {
                strcpy(entry, "..");
            }                                                     // regular entry
            else
            {
                if (inode->NM)                                     // rrip NM entry present and in effect
                {
                    //FSDEBUG("NM entry is in effect");
                    strncpy(entry, inode->nm, inode->nm_len);
                    entry[inode->nm_len] = '\0';
                }                                                 // regular ISO9660 filename
                else
                {
                    //FSDEBUG("readdir: no NM entry found, name len %d",name_len);
                    // because there can be '\0' characters because using of UCS-2 encoding we need to use memcpy
                    memcpy(entry, (char *) record->name, name_len);
                    entry[name_len] = '\0';

                    // fixup entry -- lowercase, strip leading ';', etc..
                    if (isofs_fix_entry(&entry,name_len,data->isofs->joliet_level,data->iocharset)<0)
                    {
                        FSDEBUG("error during entry fixup");
                        isofs_free_inode(inode);
                        free(buf);
                        return -EIO;
                    }
                }
            }

            // fprintf(stderr, "%d -- %s\n\n", count, entry);

            if (filler)
            {
                struct stat st;
                memset(& st, '\0', sizeof(struct stat));
                isofs_direntry2stat(& st, inode);
                rc = filler(filler_buf, entry, &st, 0);
                if (rc)
                {
                    // printf("readdir: filler return with %d, entry %s\n", rc, entry);
                    isofs_free_inode(inode);
                    free(buf);
                    free(entry);
                    return -rc;
                }
            }

            char absolute_entry[PATH_MAX];
            strcpy(absolute_entry, path);
            if (path[1] != '\0')                                   // not root dir
            {
                strcat(absolute_entry, "/");
            }
            strcat(absolute_entry, entry);
            if (g_hash_table_lookup(data->lookup_table, absolute_entry))
            {
                // already in lookup cache
                isofs_free_inode(inode);
            }
            else
            {
                FSDEBUG("REGISTER [%s] IN LOOKUP_TABLE",absolute_entry);
                g_hash_table_insert(data->lookup_table, g_strdup(absolute_entry), inode);
            }

            free(entry);

            boff += record_length;
            total_size += record_length;
            count++;
        }

        // read next block

        block++;
    }

out_readdir:
    if (retval2!=1 && real)
    {
        v_dir = opendir(newpath);
        if (v_dir)
        {
            for (;;)
            {
                v_dirent = readdir(v_dir);
                if (v_dirent == NULL) break;
                v_chemin[0] = '\0';
                if (!strcmp(newpath,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name);
                else sprintf(v_chemin, "%s/%s", newpath, v_dirent->d_name);
                inode2 = fs_lookup(v_chemin);
                if (inode2 == NULL)
                {
                    memset(&v_stbuf, '\0', sizeof(struct stat));
                    if (filler && !lstat(v_chemin,&v_stbuf))
                    {
                        filler(filler_buf, v_dirent->d_name, &v_stbuf, 0);
                        FSDEBUG("FILLER #1 [%s]",v_dirent->d_name);
                    }
                }
            }
            closedir(v_dir);
        }
    }

    if (real && data->union_mounting)
    {
        // Read the real path
        v_dir = opendir(path);
        if (v_dir)
        {
            for (;;)
            {
                retval1 = 1;
                v_dirent = readdir(v_dir);
                if (v_dirent == NULL) break;
                if (retval2 != 1)
                {
                    v_chemin[0] = '\0';
                    if (!strcmp(newpath,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name);
                    else sprintf(v_chemin, "%s/%s", newpath, v_dirent->d_name);
                    retval1 = stat(v_chemin, &v_stbuf);
                }
                v_chemin[0] = '\0';
                if (!strcmp(path,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name);
                else sprintf(v_chemin, "%s/%s", path, v_dirent->d_name);
                inode2 = fs_lookup(v_chemin);
                if (inode2==NULL && retval1!=0)
                {
                    memset(&v_stbuf, '\0', sizeof(struct stat));
                    if (filler && !lstat(v_chemin,&v_stbuf))
                    if (g_hash_table_lookup(data->removed_lookup_table,v_chemin) == NULL)
                    {
                        filler(filler_buf, v_dirent->d_name, &v_stbuf, 0);
                        FSDEBUG("FILLER #2 [%s]",v_dirent->d_name);
                    }
                }
            }
            closedir(v_dir);
        }
    }

    if (buf != NULL) free(buf);
    return 0;
}