When i am trying to create directories from zip file in mounted directory using fuse on ubuntu 20.04, they simply are not being created. In my implementation fuse has problem with giving rights to directories. If zip file has only files, there is no problem.
In main i read names from zip and separate them, if directory then it goes to directoryNames, if file then it goes to fileNames.
Then fuse gets arguments to mount point and zipfile
then i use those arrays, in get_reddir, which should send paths to get_attr, which should give directory, flag S_IFDIR, after that directories should be visible in mounted point.
compilation command: gcc -o programName filename -lzip -lfuse -D_FILE_OFFSET_BITS=64 and we can turn it like this: ./programName zipFile.zip mountPoint
Here is whole code that i have wrote:
#define FUSE_USE_VERSION 30
#include <fuse.h>
#include <zip.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define MAX_SIZE 100
zip_t *archive;
char directoryNames[255][255];
char fileNames[255][255];
int dirIndex = -1;
int fileIndex = -1;
static int do_getattr(const char *path, struct stat *st)
{
if (strcmp(path, "/") == 0)
{
st->st_mode = S_IFDIR | 0777;
st->st_nlink = 2;
}
else if (path[strlen(path) - 1] == '/')
{
st->st_mode = S_IFDIR | 0777;
st->st_nlink = 1;
st->st_size = 1024;
}
else
{
st->st_mode = S_IFREG | 0777;
st->st_nlink = 1;
st->st_size = 1024;
}
return 0;
}
static int readdir_callback(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
(void)offset;
(void)fi;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
if (strcmp(path, "/") == 0)
{
int num_directories = sizeof(directoryNames) / sizeof(directoryNames[0]);
for (int i = 0; i < num_directories; i++)
{
if (directoryNames[i][0] != '\0')
{
printf("FILLED Directories %s\n", directoryNames[i]);
filler(buf, directoryNames[i], NULL, 0);
}
else
{
break;
}
}
int num_files = sizeof(fileNames) / sizeof(fileNames[0]);
for (int k = 0; k < num_files; k++)
{
if (fileNames[k][0] != '\0')
{
filler(buf, fileNames[k], NULL, 0);
// printf("FILLED Files %s\n", fileNames[k]);
}
else
{
break;
}
}
}
return 0;
}
static int do_read(const char *path, char *buffer, size_t size, off_t offset, struct fuse_file_info *fi)
{
int num_entries = zip_get_num_entries(archive, 0);
for (int i = 0; i < num_entries; i++)
{
const char *entry_name = zip_get_name(archive, i, 0);
char name[MAX_SIZE];
snprintf(name, MAX_SIZE, "/%s", entry_name);
if (strcmp(path, name) == 0)
{
struct zip_file *entry_file = zip_fopen_index(archive, i, 0);
if (entry_file == NULL)
{
printf("Failed to open entry file '%s'\n", entry_name);
continue;
}
long fileSize = 1024;
char *content = (char *)malloc(fileSize + 1);
zip_int64_t bytes_read = zip_fread(entry_file, content, fileSize);
memcpy(buffer, content + offset, size);
return strlen(content) - offset;
}
}
return 0;
}
static struct fuse_operations operations = {
.getattr = do_getattr,
.readdir = readdir_callback,
.read = do_read,
};
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("not enought input arguments");
return 0;
}
int error;
archive = zip_open(argv[1], ZIP_RDONLY, &error);
if (archive == NULL)
{
printf("Failed to open: %s\n", argv[1]);
return 0;
}
memset(directoryNames, 0, sizeof(directoryNames));
memset(fileNames, 0, sizeof(fileNames));
int num_entries = zip_get_num_entries(archive, 0);
for (int i = 0; i < num_entries; i++)
{
const char *entry_name = zip_get_name(archive, i, 0);
if (entry_name[strlen(entry_name) - 1] == '/')
{
char dirName[255];
dirIndex++;
strcpy(dirName, entry_name);
strcpy(directoryNames[dirIndex], dirName);
}
else
{
char fileName[255];
fileIndex++;
strcpy(fileName, entry_name);
strcpy(fileNames[fileIndex], fileName);
}
}
return fuse_main(argc - 1, argv + 1, &operations, NULL);
}