Ejemplo n.º 1
0
int fs_real_statfs(const char *path, struct statfs *stbuf)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    fusioniso_data *data=fusioniso_get_data();

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

    isofs_inode *inode=NULL;
    if (data->glibc && strcmp(path,"/lib/ld-linux.so.2")==0) return statfs("/lib/ld-klik2.so.2", stbuf);
    if (data->union_mounting) inode=fs_lookup(path);
    if (!data->union_mounting || inode)
    {
        stbuf->f_type = ISOFS_SUPER_MAGIC;
        stbuf->f_bsize = data->isofs->data_size;                // or PAGE_CACHE_SIZE?
        stbuf->f_blocks = 0;                                      // while it is possible to calculate this, i see no reasons to do so
        stbuf->f_bfree = 0;
        stbuf->f_bavail = 0;
        stbuf->f_files = 0;
        stbuf->f_ffree = 0;
        stbuf->f_namelen = NAME_MAX - 1;                          // ? not sure..
        return 0;
    }

    fs_home(path, &newpath);
    if (statfs(newpath,stbuf) == 0) return 0;
    return -errno;
}
Ejemplo n.º 2
0
int fs_real_symlink(const char *path1, const char *path2)
{
    char sppath2[FS_MAXPATH];
    char *spath2=sppath2;

    FSDEBUG("path1=%s -> path2=%s",path1,path2);
    isofs_inode *inode = fs_lookup(path2);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path2);
        return -EPERM;
    }

    if (fs_home(path2,&spath2) == 0)
    {
        fs_path_mkdir(spath2, 1);
        FSDEBUG("#1 path1=%s -> spath2=%s",path1,spath2);
        if (symlink(path1,spath2) == 0) return 0;
        return -errno;
    }

    FSDEBUG("#2 path1=%s -> path2=%s",path1,path2);
    if (symlink(path1,path2) == 0) return 0;
    return -errno;
}
Ejemplo n.º 3
0
int fs_real_getxattr(const char *path, const char *name, void *value, size_t size)
{
    char ppath[2*FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    int retval;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -ENOTSUP;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
    {
        retval = getxattr(newpath, name, value, size);
        if (retval == -1) return -errno;
        return retval;
    }

    retval = getxattr(path, name, value, size);
    if (retval == -1) return -errno;
    return retval;
}
Ejemplo n.º 4
0
/*
 * check access permissions for a file
 */
int 
access(const char *name, oskit_mode_t mode)
{
	oskit_file_t *f;
	oskit_error_t rc = fs_lookup(name, FSLOOKUP_FOLLOW, &f);

	if (!rc) {
		rc = oskit_file_access(f, (oskit_mode_t) mode);
		oskit_file_release(f);
	}
	return rc ? (errno = rc), -1 : 0;
}
Ejemplo n.º 5
0
int
chmod(const char *name, oskit_mode_t mode)
{
	oskit_file_t *f;
	oskit_error_t rc = fs_lookup(name, FSLOOKUP_FOLLOW, &f);

	if (!rc) {
		struct oskit_stat sb;
		sb.mode = mode;
		rc = oskit_file_setstat(f, OSKIT_STAT_MODE, &sb);
		oskit_file_release(f);
	}
	return rc ? (errno = rc), -1 : 0;
}
Ejemplo n.º 6
0
int fs_real_rmdir(const char *path)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    struct stat v_stbuf;
    int retval, errno2;
    fusioniso_data *data=fusioniso_get_data();

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

    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -EPERM;
    }

    switch(fs_home_stat(path,&newpath,&v_stbuf))
    {
        case 0:
            FSDEBUG("#1 rmdir(%s)",newpath);
            retval = rmdir(newpath);
	    errno2 = errno;
            // If the file exist on disk,
            // we keep the file name in a list
            if (lstat(path,&v_stbuf) == 0)
            {
                FSDEBUG("INSERT removed_lookup_table -> %s",path);
                g_hash_table_insert(data->removed_lookup_table, g_strdup(path), removed_value);
                return 0;
            }
            if (retval == 0) return 0;
	    return -errno2;
        case -1:
            // If the file exist on disk,
            // we keep the file name in a list
            if (lstat(path,&v_stbuf) == 0)
            {
                FSDEBUG("INSERT removed_lookup_table -> %s",path);
                g_hash_table_insert(data->removed_lookup_table, g_strdup(path), removed_value);
                return 0;
            }
    }
    FSDEBUG("#2 rmdir(%s)",newpath);
    if (rmdir(newpath) == 0) return 0;
    return -errno;
}
Ejemplo n.º 7
0
int fs_real_mknod(const char *path, mode_t mode, dev_t dev)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    mode_t mode2 = mode;
    FSDEBUG("path=%s mode=%d dev=%ld",path,mode,(long)dev);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -EPERM;
    }
    if (fs_home(path,&newpath) == 0) fs_path_mkdir(newpath,1);
    if (mode == 32768) mode2=33188; /* temporary fix */
    if (mknod(newpath,mode2,dev) == 0) return 0;
    return -errno;
}
Ejemplo n.º 8
0
int fs_real_utime(const char *path, struct utimbuf *times)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -ENOENT;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == -1) fs_file_dup(path,newpath);
    if (utime(newpath,times) == 0) return 0;
    return -errno;
}
Ejemplo n.º 9
0
int fs_real_removexattr(const char *path, const char *name)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -ENOTSUP;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == -1) fs_file_dup(path,newpath);
    if (removexattr(newpath,name) == 0) return 0;
    return -errno;
}
Ejemplo n.º 10
0
int fs_real_truncate(const char *path, off_t length)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -EPERM;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == -1) fs_file_dup(path,newpath);
    if (truncate(newpath,length) == 0) return 0;
    return -errno;
}
Ejemplo n.º 11
0
int fs_real_chown(const char *path, uid_t owner, gid_t group)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -EPERM;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == -1) fs_file_dup(path,newpath);
    if (chown(newpath,owner,group) == 0) return 0;
    return -errno;
}
Ejemplo n.º 12
0
int fs_real_mkdir(const char *path, mode_t mode)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -EPERM;
    }

    if (fs_home(path,&newpath) == 0) fs_path_mkdir(newpath,1);
    FSDEBUG("newpath=%s mode=%d", newpath, mode);

    if (mkdir(newpath,mode) == 0) return 0;
    return -errno;
}
Ejemplo n.º 13
0
int fs_real_rename(const char *oldpath, const char *newpath)
{
    char ppath1[FS_MAXPATH],ppath2[FS_MAXPATH];
    struct stat v_stbuf;
    char *path1=ppath1;
    char *path2=ppath2;
    int retval;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("oldpath=%s -> newpath=%s",oldpath,newpath);

    isofs_inode *inode = fs_lookup(oldpath);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",oldpath);
        return -EPERM;
    }
    retval = fs_home_stat(oldpath,&path1,&v_stbuf);
    if (fs_home(newpath,&path2)==0 || retval!=1)
    {
        if (retval == -1)
        {
            retval = stat(oldpath, &v_stbuf);
            if (!retval && S_ISDIR(v_stbuf.st_mode))
            {
                //printf("TODO\n");
                //fflush(stdout);
		FSDEBUG("not yet implemented");
            }
            else fs_file_dup(oldpath,path1);
            FSDEBUG("INSERT removed_lookup_table -> %s",oldpath);
            g_hash_table_insert(data->removed_lookup_table, g_strdup(oldpath), removed_value);
        }
        fs_path_mkdir(path2, 1);

        FSDEBUG("#1 path1=%s -> path2=%s",path1,path2);
        if (rename(path1,path2) == 0) return 0;
        return -errno;
    }
    FSDEBUG("#2 oldpath=%s -> newpath=%s",oldpath,newpath);
    if (rename(oldpath,newpath) == 0) return 0;
    return -errno;
}
Ejemplo n.º 14
0
int fs_real_write(const char *path, const char *out_buf, size_t size, off_t offset)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    int v_file, v_count, retval;
    char *newpath=ppath;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("path=%s (%d octets, %d offset)",path,size,(int)offset);

    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s", path);
        return -EPERM;
    }

    retval = fs_home_stat(path, &newpath, &v_stbuf);
    if (retval != 1)
    {
        if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
        if (retval == -1) fs_file_dup(path,newpath);
        v_file = open(newpath, O_RDWR|O_APPEND);
        if (v_file == -1) return -EACCES;
        ftruncate(v_file, offset);
        v_count = write(v_file, out_buf, size);
        close(v_file);
        return size;
    }

    if (data->union_mounting && stat(path,&v_stbuf)==0)
    {
        if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL;
        v_file = open(path, O_RDWR|O_APPEND);
        if (v_file == -1) return -EACCES;
        ftruncate(v_file, offset);
        v_count = write(v_file, out_buf, size);
        close(v_file);
        return size;
    }
    return -ENOENT;
}
Ejemplo n.º 15
0
int fs_real_access(const char *path, int amode)
{
    char ppath[2*FS_MAXPATH];
    char *newpath=ppath;
    struct stat v_stbuf;
    fusioniso_data *data=fusioniso_get_data();

    FSDEBUG("path=%s mode=%d",path,amode);

    isofs_inode *inode = fs_lookup(path);
    if (inode) return 0;
    if (data->sandbox_mounting==sandbox_data && (amode&W_OK)) return 0;
    if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
    {
        if (access(newpath,amode) == 0) return 0;
        return -errno;
    }
    if (access(path,amode) == 0) return 0;
    return -errno;
}
Ejemplo n.º 16
0
int fs_real_listxattr(const char *path, char *list, size_t size)
{
    char ppath[FS_MAXPATH];
    struct stat v_stbuf;
    char *newpath=ppath;
    FSDEBUG("path=%s",path);
    isofs_inode *inode = fs_lookup(path);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",path);
        return -ENOTSUP;
    }

    if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
    {
        if (listxattr(newpath,list,size) == 0) return 0;
        return -errno;
    }
    if (listxattr(path,list,size) == 0) return 0;
    return -errno;
}
Ejemplo n.º 17
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;
}
Ejemplo n.º 18
0
int fs_real_link(const char *oldpath, const char *newpath)
{
    char ppath2[FS_MAXPATH];
    char *path2=ppath2;
    FSDEBUG("oldpath=%s -> newpath=%s",oldpath,newpath);
    isofs_inode *inode = fs_lookup(oldpath);
    if (inode)
    {
        FSDEBUG("you don't have permission on %s",oldpath);
        return -EPERM;
    }

    if (fs_home(newpath,&path2) == 0)
    {
        fs_path_mkdir(path2, 1);
        FSDEBUG("#1: oldpath=%s -> path2=%s",oldpath,path2);
        if (link(oldpath,path2) == 0) return 0;
        return -errno;
    }
    FSDEBUG("#2: oldpath=%s -> newpath=%s",oldpath,newpath);
    if (link(oldpath,newpath) == 0) return 0;
    return -errno;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
/*
 * ディレクトリを削除する。
 *
 */
W sfs_i_rmdir (struct inode *parent, char *fname,
	       struct access_info *acc)
{
  int	nentry;
  int	i;
  int	inodeindex;
  struct inode *ip;
  W	rsize, errno;
  
  errno = fs_lookup (parent, fname, O_RDWR, 0, acc, &ip);
  if (errno) {
    printk("[PM] sfs_i_rmdir: can't remove directory %s(%d)\n", fname, errno);
    return (errno);
  }
  if ((ip->i_mode & SFS_FMT_DIR) == 0) {
    fs_close_file(ip);
    return (EP_NOTDIR);
  }
  if (ip->i_refcount >= 2) {
    fs_close_file(ip);
    return (EP_BUSY);
  }
  nentry = sfs_read_dir (ip, 0, NULL);
  if (nentry >= 3) {
    fs_close_file(ip);
    return (EP_NOTEMPTY);
  }

  nentry = sfs_read_dir (parent, 0, NULL);
  if (nentry <= 0) {
    fs_close_file(ip);
    return (EP_NOENT);
  }
  {
    struct sfs_dir buf[nentry]; /* GCC の拡張機能を使っている */
    if (sfs_read_dir (parent, nentry, buf) != 0) {
      fs_close_file(ip);
      return (EP_IO);
    }

    for (i = 0; i < nentry; i++) {
      /* 表示文字長を SFS_MAXNAMELEN にするため.後に pad があるので大丈夫 */
      if (strncmp (fname, buf[i].sfs_d_name, SFS_MAXNAMELEN+1) == 0) {
	inodeindex = buf[i].sfs_d_index;
	break;
      }
    }
    if (i >= nentry) {
      fs_close_file(ip);
      return (EP_NOENT);
    }

    while (i < nentry) {
      buf[i].sfs_d_index = buf[i + 1].sfs_d_index;
      /* 表示文字長を SFS_MAXNAMELEN にするため.後に pad があるので大丈夫 */
      strncpy (buf[i].sfs_d_name, buf[i + 1].sfs_d_name, SFS_MAXNAMELEN+1);
      i++;
    }
    i = parent->i_size - sizeof (struct sfs_dir);
    sfs_i_write(parent, 0, (B *)buf, i, &rsize);
    sfs_i_truncate (parent, i);

    ip->i_link--;
    ip->i_dirty = 1;
    if (ip->i_link <= 1) {
      sfs_i_truncate (ip, 0);
      sfs_free_inode(ip->i_fs, inodeindex);
    }
    parent->i_link -= 1;
    parent->i_dirty = 1;
  }
  fs_close_file(ip);
  return (EP_OK);
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
int fs_real_readlink(const char *path, char *target, size_t size)
{
    char ppath[FS_MAXPATH];
    char *newpath=ppath;
    int retval;
    fusioniso_data *data=fusioniso_get_data();

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

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

        // Use our own loader
        if (data->glibc && strcmp(path,"/lib/ld-linux.so.2")==0)
        {
            retval = readlink("/lib/ld-klik2.so.2", target, size-1);
            if (retval == -1) return -errno;
            target[retval] = '\0';
            return 0;
        }

        if (fs_home_stat(path,&newpath,&v_stbuf) == 0)
        {
            if (!S_ISLNK(v_stbuf.st_mode)) return -EINVAL;
            retval = readlink(newpath, target, size-1);
            if (retval == -1) return -errno;
            target[retval] = '\0';
            strcpy(newpath, data->sandbox_path);
            strcat(newpath, target);
            if (data->sandbox_mounting!=sandbox_none && stat(newpath,&v_stbuf)==0)
            {
                strcpy(target, newpath);
                return 0;
            }
            return 0;
        }

        if (data->union_mounting && lstat(path,&v_stbuf)==0)
        {
            if (!S_ISLNK(v_stbuf.st_mode)) return -EINVAL;
            retval = readlink(path, target, size-1);
            if (retval == -1) return -errno;
            target[retval] = '\0';
            /*if (lstat(target,&v_stbuf)==-1 && fs_lookup(target))
            {
                sprintf(ppath,"%s%s", data->mountpoint, target);
                strcpy(target, ppath);
            }*/
            return 0;
        }

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

    if (!inode->PX || !inode->SL || !S_ISLNK(inode->st.st_mode))
    {
        FSDEBUG("%s not a link", path);
        return -EINVAL;
    }
    strncpy(target, inode->sl, size - 1);
    target[size - 1] = '\0';
    return 0;
}
Ejemplo n.º 23
0
int fs_real_getattr(const char *path, struct stat *stbuf)
{
    char ppath[FS_MAXPATH], target[FS_MAXPATH];
    char *newpath=ppath;
    int i, j;
    fusioniso_data *data=fusioniso_get_data();

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

    isofs_inode *inode = fs_lookup(path);
    if (inode == NULL)
    {
        if (data->glibc && strcmp(path,"/lib/ld-linux.so.2")==0)
        {
            if (lstat("/lib/ld-klik2.so.2",stbuf) == 0) return 0;
            return -ENOENT;
        }

        // we forbid access to the location where all mount points are located
        if (data->union_mounting)
        {
            for (i=0,j=0; i<data->base_root_size && path[j]!='\0';) {
                if (data->base_root[i] != path[j]) break;
                if (path[j] == '/') for (;path[j]=='/';j++);
                else j++;
                i++;
            }
            if (data->base_root[i] == '\0') return -ENOENT;
        }

        if (fs_home_stat(path,&newpath,stbuf) == 0) return 0;
        if (data->union_mounting && lstat(path,stbuf)==0)
        {
            int retval;

            // If a file was previously removed, we need to take care
            if (g_hash_table_lookup(data->removed_lookup_table, path))
            {
                FSDEBUG("LOOKUP removed_lookup_table -> %s",path);
                return -ENOENT;
            }

            // Point to a file located into the iso image
            retval = readlink(path, target, FS_MAXPATH-1);
            if (retval != -1)
            {
                target[retval] = '\0';
                // stbuf->st_size += strlen(data->mountpoint);
            }

            return 0;
        }
        // this error occur too often when browsing mounted tree with konqueror --
        // it check existence of .directory file with stat()
        FSDEBUG("know nothing about %s",path);
        return -ENOENT;
    }

    FSDEBUG("found %s, size %d",path,isonum_733(inode->record->size));
    memset(stbuf, 0, sizeof(struct stat));
    isofs_direntry2stat(stbuf, inode);
    /*    if (ISO_FLAGS_DIR(inode->record->flags)) {
                        printf("%s %i %i\n", path, (int) stbuf->st_size, stbuf->st_mode);
                    }*/

    return 0;
}
Ejemplo n.º 24
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;
}