minimig: support for shared folder.

This commit is contained in:
sorgelig
2020-06-29 08:19:25 +08:00
parent 4b6a27750e
commit 1f9935d080
8 changed files with 1157 additions and 2 deletions

View File

@@ -30,7 +30,7 @@
<NMakeOutput>MiSTer</NMakeOutput>
<NMakeCleanCommandLine>git.lnk ./clean.sh</NMakeCleanCommandLine>
<NMakePreprocessorDefinitions>__arm__;__GNUC__;__USE_GNU ;_GNU_SOURCE;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng</NMakeIncludeSearchPath>
<NMakeIncludeSearchPath>c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1\arm-linux-gnueabihf;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng</NMakeIncludeSearchPath>
<OutDir>$(TEMP)</OutDir>
<IntDir>$(TEMP)</IntDir>
<AdditionalOptions>
@@ -86,6 +86,7 @@
<ClCompile Include="support\minimig\minimig_config.cpp" />
<ClCompile Include="support\minimig\minimig_fdd.cpp" />
<ClCompile Include="support\minimig\minimig_hdd.cpp" />
<ClCompile Include="support\minimig\minimig_share.cpp" />
<ClCompile Include="support\neogeo\neogeo_loader.cpp" />
<ClCompile Include="support\pcecd\pcecd.cpp" />
<ClCompile Include="support\pcecd\pcecdd.cpp" />
@@ -142,11 +143,13 @@
<ClInclude Include="support\archie\archie.h" />
<ClInclude Include="support\c64\c64.h" />
<ClInclude Include="support\megacd\megacd.h" />
<ClInclude Include="support\minimig\miminig_fs_messages.h" />
<ClInclude Include="support\minimig\minimig_boot.h" />
<ClInclude Include="support\minimig\minimig_config.h" />
<ClInclude Include="support\minimig\minimig_fdd.h" />
<ClInclude Include="support\minimig\minimig_hdd.h" />
<ClInclude Include="support\minimig\minimig_hdd_internal.h" />
<ClInclude Include="support\minimig\minimig_share.h" />
<ClInclude Include="support\neogeo\neogeo_loader.h" />
<ClInclude Include="support\pcecd\pcecd.h" />
<ClInclude Include="support\sharpmz\sharpmz.h" />

View File

@@ -196,6 +196,9 @@
<ClCompile Include="audio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="support\minimig\minimig_share.cpp">
<Filter>Source Files\support</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h">
@@ -369,5 +372,11 @@
<ClInclude Include="audio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="support\minimig\minimig_share.h">
<Filter>Header Files\support</Filter>
</ClInclude>
<ClInclude Include="support\minimig\miminig_fs_messages.h">
<Filter>Header Files\support</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -3,6 +3,7 @@
#include "support/minimig/minimig_boot.h"
#include "support/minimig/minimig_fdd.h"
#include "support/minimig/minimig_hdd.h"
#include "support/minimig/minimig_share.h"
// SharpMz support
#include "support/sharpmz/sharpmz.h"

View File

@@ -0,0 +1,378 @@
#define ACTION_NIL 0
#define ACTION_GET_BLOCK 2
#define ACTION_SET_MAP 4
#define ACTION_DIE 5
#define ACTION_EVENT 6
#define ACTION_CURRENT_VOLUME 7
#define ACTION_LOCATE_OBJECT 8
#define ACTION_RENAME_DISK 9
#define ACTION_WRITE 'W'
#define ACTION_READ 'R'
#define ACTION_FREE_LOCK 15
#define ACTION_DELETE_OBJECT 16
#define ACTION_RENAME_OBJECT 17
#define ACTION_MORE_CACHE 18
#define ACTION_COPY_LOCK 19
#define ACTION_WAIT_CHAR 20
#define ACTION_SET_PROTECT 21
#define ACTION_CREATE_DIR 22
#define ACTION_EXAMINE_OBJECT 23
#define ACTION_EXAMINE_NEXT 24
#define ACTION_DISK_INFO 25
#define ACTION_INFO 26
#define ACTION_FLUSH 27
#define ACTION_SET_COMMENT 28
#define ACTION_PARENT 29
#define ACTION_TIMER 30
#define ACTION_INHIBIT 31
#define ACTION_DISK_TYPE 32
#define ACTION_DISK_CHANGE 33
#define ACTION_SET_DATE 34
#define ACTION_SCREEN_MODE 994
#define ACTION_READ_RETURN 1001
#define ACTION_WRITE_RETURN 1002
#define ACTION_FINDUPDATE 1004
#define ACTION_FINDINPUT 1005
#define ACTION_FINDOUTPUT 1006
#define ACTION_END 1007
#define ACTION_SEEK 1008
#define ACTION_TRUNCATE 1022
#define ACTION_WRITE_PROTECT 1023
#define ERROR_NO_FREE_STORE 103
#define ERROR_TASK_TABLE_FULL 105
#define ERROR_LINE_TOO_LONG 120
#define ERROR_FILE_NOT_OBJECT 121
#define ERROR_INVALID_RESIDENT_LIBRARY 122
#define ERROR_NO_DEFAULT_DIR 201
#define ERROR_OBJECT_IN_USE 202
#define ERROR_OBJECT_EXISTS 203
#define ERROR_DIR_NOT_FOUND 204
#define ERROR_OBJECT_NOT_FOUND 205
#define ERROR_BAD_STREAM_NAME 206
#define ERROR_OBJECT_TOO_LARGE 207
#define ERROR_ACTION_NOT_KNOWN 209
#define ERROR_INVALID_COMPONENT_NAME 210
#define ERROR_INVALID_LOCK 211
#define ERROR_OBJECT_WRONG_TYPE 212
#define ERROR_DISK_NOT_VALIDATED 213
#define ERROR_DISK_WRITE_PROTECTED 214
#define ERROR_RENAME_ACROSS_DEVICES 215
#define ERROR_DIRECTORY_NOT_EMPTY 216
#define ERROR_TOO_MANY_LEVELS 217
#define ERROR_DEVICE_NOT_MOUNTED 218
#define ERROR_SEEK_ERROR 219
#define ERROR_COMMENT_TOO_BIG 220
#define ERROR_DISK_FULL 221
#define ERROR_DELETE_PROTECTED 222
#define ERROR_WRITE_PROTECTED 223
#define ERROR_READ_PROTECTED 224
#define ERROR_NOT_A_DOS_DISK 225
#define ERROR_NO_DISK 226
#define ERROR_NO_MORE_ENTRIES 232
#define SHARED_LOCK -2
#define EXCLUSIVE_LOCK -1
#define MODE_OLDFILE 1005
#define MODE_NEWFILE 1006
#define MODE_READWRITE 1004
#define OFFSET_BEGINNING -1
#define OFFSET_CURRENT 0
#define OFFSET_END 1
#define ST_ROOT 1
#define ST_USERDIR 2
#define ST_SOFTLINK 3
#define ST_LINKDIR 4
#define ST_FILE -3
#define ST_LINKFILE -4
#define ST_PIPEFILE -5
#pragma pack(push, 1)
struct GenericRequestResponse
{
long sz;
union
{
struct
{
long type;
long key;
};
struct
{
long success;
long error_code;
};
};
};
struct LocateObjectRequest
{
long sz;
long type;
long key;
long mode;
char name[1];
};
struct LocateObjectResponse
{
long sz;
long success;
long error_code;
long key;
};
struct FreeLockRequest
{
long sz;
long type;
long key;
};
struct FreeLockResponse
{
long sz;
long success;
long error_code;
};
struct CopyDirRequest
{
long sz;
long type;
long key;
};
struct CopyDirResponse
{
long sz;
long success;
long error_code;
long key;
};
struct ParentRequest
{
long sz;
long type;
long key;
};
struct ParentResponse
{
long sz;
long success;
long error_code;
long key;
};
struct ExamineObjectRequest
{
long sz;
long type;
long key;
long disk_key;
};
struct ExamineObjectResponse
{
long sz;
long success;
long error_code;
long disk_key;
long entry_type;
int size;
int protection;
int date[3];
char file_name[1];
};
struct FindXxxRequest
{
long sz;
long type;
long key;
char name[1];
};
struct FindXxxResponse
{
long sz;
long success;
long error_code;
long arg1;
};
struct ReadRequest
{
long sz;
long type;
long arg1;
int address;
int length;
};
struct ReadResponse
{
long sz;
long success;
long error_code;
int actual;
};
struct WriteRequest
{
long sz;
long type;
long arg1;
int address;
int length;
};
struct WriteResponse
{
long sz;
long success;
long error_code;
int actual;
};
struct SeekRequest
{
long sz;
long type;
long arg1;
int new_pos;
int mode;
};
struct SeekResponse
{
long sz;
long success;
long error_code;
int old_pos;
};
struct EndRequest
{
long sz;
long type;
long arg1;
};
struct EndResponse
{
long sz;
long success;
long error_code;
};
struct DeleteObjectRequest
{
long sz;
long type;
long key;
char name[1];
};
struct DeleteObjectResponse
{
long sz;
long success;
long error_code;
};
struct RenameObjectRequest
{
long sz;
long type;
long key;
long target_dir;
unsigned char name_len;
unsigned char new_name_len;
char name[1];
};
struct RenameObjectResponse
{
long sz;
long success;
long error_code;
};
struct CreateDirRequest
{
long sz;
long type;
long key;
char name[1];
};
struct CreateDirResponse
{
long sz;
long success;
long error_code;
long key;
};
struct SetProtectRequest
{
long sz;
long type;
long key;
long mask;
char name[1];
};
struct SetProtectResponse
{
long sz;
long success;
long error_code;
};
struct SetCommentRequest
{
long sz;
long type;
long key;
unsigned char name_len;
unsigned char comment_len;
};
struct SetCommentResponse
{
long sz;
long success;
long error_code;
};
struct DiskInfoRequest
{
long sz;
long type;
long key;
long dummy1;
long dummy2;
};
struct DiskInfoResponse
{
long sz;
long success;
long error_code;
unsigned long total;
unsigned long used;
long update;
};
#pragma pack(pop)

View File

@@ -15,6 +15,7 @@
#include "minimig_fdd.h"
#include "minimig_hdd.h"
#include "minimig_config.h"
#include "minimig_share.h"
const char *config_memory_chip_msg[] = { "512K", "1M", "1.5M", "2M" };
const char *config_memory_slow_msg[] = { "none", "512K", "1M", "1.5M" };
@@ -502,6 +503,7 @@ void minimig_reset()
{
ApplyConfiguration(0);
user_io_rtc_reset();
minimig_share_reset();
}
void minimig_set_kickstart(char *name)

View File

@@ -0,0 +1,751 @@
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <dirent.h>
#include <sys/mman.h>
#include <time.h>
#include <map>
#include <string>
#include <vector>
#include "../../hardware.h"
#include "../../file_io.h"
#include "../../user_io.h"
#include "../../spi.h"
#include "miminig_fs_messages.h"
#define SHMEM_ADDR 0x27FF4000
#define SHMEM_SIZE 0x2000
static uint8_t *shmem = 0;
#define REQUEST_FLG 0 // 4B
#define REQUEST_BUFFER 4 // ~512B
#define DATA_BUFFER 0x1000 // 4KB
//#define DEBUG
#ifdef DEBUG
#define dbg_print printf
#define dbg_hexdump hexdump
#else
#define dbg_print(x,...) void()
#define dbg_hexdump(x,...) void()
#endif
#define SWAP_INT(a) ((((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24))
static char basepath[1024] = {};
static int baselen = 0;
struct lock
{
uint16_t mode;
std::string path;
std::vector<dirent64> dir_items;
};
static std::map<uint32_t, lock> locks;
static uint32_t next_key = 1;
static uint32_t get_key()
{
uint32_t key;
do
{
key = next_key;
if (next_key == INT32_MAX) next_key = 1; else next_key++;
} while (locks.find(key) != locks.end());
return key;
}
static uint32_t add_lock(uint16_t mode, const char* path)
{
uint32_t key = get_key();
locks[key] = { mode, path, {} };
dbg_print("+ add lock: %d, %s\n", key, path);
return key;
}
static int has_locks(const char* path)
{
int has = 0;
for (const auto &pair : locks)
{
if (pair.second.path == path)
{
if (!has)
{
dbg_print("! path %s has locks:", path);
}
has = 1;
dbg_print(" %d", pair.first);
}
}
if (has)
{
dbg_print("\n");
}
return has;
}
static std::map<uint32_t, fileTYPE> open_file_handles;
static uint32_t next_fp = 1;
static uint32_t get_fp()
{
uint32_t fp;
do
{
fp = next_fp;
if (next_fp == INT32_MAX) next_fp = 1; else next_fp++;
} while (open_file_handles.find(fp) != open_file_handles.end());
return fp;
}
static char* find_path(uint32_t key, const char *name)
{
dbg_print("find_path(%d, %s)\n", key, name);
static char str[1024] = {};
const char* p = strchr(name, ':');
if (p)
{
key = 0;
name = p + 1;
}
strcpy(str, basepath);
if (key)
{
auto it = locks.find(key);
if (it != locks.end()) strcpy(str, it->second.path.c_str());
}
if (PathIsDir(str))
{
if (strlen(name))
{
strcat(str, "/");
strcat(str, name);
dbg_print("check path: %s\n", str);
char *p = strrchr(str, '/');
if (!p) str[0] = 0;
else
{
*p = 0;
if (!PathIsDir(str)) str[0] = 0;
else *p = '/';
}
}
}
else
{
str[0] = 0;
}
dbg_print("returned path: %s\n", str);
return str;
}
static int process_request(void *reqres_buffer)
{
static char buf[1024];
GenericRequestResponse *reqres = ( GenericRequestResponse *)reqres_buffer;
int rtype = SWAP_INT(reqres->type);
int ret = ERROR_ACTION_NOT_KNOWN;
int sz = SWAP_INT(reqres->sz);
((uint8_t*)reqres_buffer)[sz] = 0;
int sz_res = sizeof(GenericRequestResponse);
dbg_print("request type: %d, struct size: %d\n", rtype, sz);
dbg_hexdump(reqres_buffer, sz, 0);
if (!baselen)
{
strcpy(basepath, HomeDir());
strcat(basepath, "/shared");
baselen = strlen(basepath);
FileCreatePath(basepath);
}
switch (rtype)
{
case ACTION_LOCATE_OBJECT:
{
dbg_print("> ACTION_LOCATE_OBJECT\n");
LocateObjectRequest *req = (LocateObjectRequest*)reqres_buffer;
LocateObjectResponse *res = (LocateObjectResponse*)reqres_buffer;
sz_res = sizeof(LocateObjectResponse);
char *str = find_path(SWAP_INT(req->key), req->name + 1);
if (!str[0])
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
if (!FileExists(str) && !PathIsDir(str))
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t key = add_lock(req->mode, str);
res->key = SWAP_INT(key);
ret = 0;
}
break;
case ACTION_FREE_LOCK:
{
dbg_print("> ACTION_FREE_LOCK\n");
FreeLockRequest *req = (FreeLockRequest*)reqres_buffer;
uint32_t key = SWAP_INT(req->key);
locks.erase(key);
dbg_print(" lock: %d\n", key);
ret = 0;
}
break;
case ACTION_COPY_LOCK:
{
dbg_print("> ACTION_COPY_LOCK\n");
CopyDirRequest *req = (CopyDirRequest*)reqres_buffer;
CopyDirResponse *res = (CopyDirResponse*)reqres_buffer;
sz_res = sizeof(CopyDirResponse);
uint32_t key = SWAP_INT(req->key);
if (locks.find(key) == locks.end())
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t new_key = add_lock(locks[key].mode, locks[key].path.c_str());
dbg_print("CopyDir: %s: %d -> %d\n", locks[new_key].path.c_str(), key, new_key);
res->key = SWAP_INT(new_key);
ret = 0;
}
break;
case ACTION_PARENT:
{
dbg_print("> ACTION_PARENT\n");
ParentRequest *req = (ParentRequest*)reqres_buffer;
ParentResponse *res = (ParentResponse*)reqres_buffer;
sz_res = sizeof(ParentResponse);
uint32_t key = SWAP_INT(req->key);
dbg_print(" current key: %d\n", key);
if (locks.find(key) == locks.end())
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
ret = 0;
res->key = 0;
char *name = buf;
strcpy(name, locks[key].path.c_str());
dbg_print(" current path: %s\n", name);
if (!strncasecmp(basepath, name, baselen)) name += baselen;
if (strlen(name))
{
char* p = strrchr(name, '/');
if (p)
{
*p = 0;
uint32_t key = add_lock(SHARED_LOCK, buf);
res->key = SWAP_INT(key);
dbg_print(" parent path: %s\n", buf);
dbg_print(" parent path: %s\n", buf);
}
}
}
break;
case ACTION_EXAMINE_NEXT:
case ACTION_EXAMINE_OBJECT:
{
dbg_print("> ACTION_EXAMINE\n");
ExamineObjectRequest *req = (ExamineObjectRequest*)reqres_buffer;
ExamineObjectResponse *res = (ExamineObjectResponse*)reqres_buffer;
sz_res = sizeof(ExamineObjectResponse);
uint32_t key = SWAP_INT(req->key);
dbg_print(" key: %d\n", key);
char *name = buf;
name[0] = 0;
if (locks.find(key) != locks.end()) strcpy(name, locks[key].path.c_str());
if (!strlen(name)) strcpy(name, basepath);
int disk_key = 666;
static char fn[256];
if (rtype == ACTION_EXAMINE_OBJECT)
{
dbg_print(" examine first\n");
if (!strlen(name + baselen)) strcpy(fn, "MiSTer");
else
{
const char *p = strrchr(name, '/');
strcpy(fn, p ? p + 1 : name);
}
locks[key].dir_items.clear();
if (PathIsDir(name))
{
const char* full_path = getFullPath(name);
DIR *d = opendir(full_path);
if (!d)
{
printf("Couldn't open dir: %s\n", full_path);
ret = ERROR_OBJECT_WRONG_TYPE;
break;
}
struct dirent64 *de;
while ((de = readdir64(d)))
{
if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) continue;
locks[key].dir_items.push_back(*de);
}
closedir(d);
}
}
else
{
dbg_print(" examine next\n");
disk_key = SWAP_INT(req->disk_key);
uint32_t listed = disk_key - 666;
disk_key++;
if (listed >= locks[key].dir_items.size())
{
locks[key].dir_items.clear();
ret = ERROR_NO_MORE_ENTRIES;
break;
}
strcat(name, "/");
strcat(name, locks[key].dir_items[listed].d_name);
memcpy(fn, locks[key].dir_items[listed].d_name, sizeof(fn));
ret = 0;
}
dbg_print(" name: %s\n", name);
dbg_print(" fn: %s\n", fn);
int type = 0;
if (FileExists(name)) type = ST_FILE;
else if (PathIsDir(name)) type = ST_USERDIR;
else
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
time_t time = 0;
uint32_t size = 0;
struct stat64 *st = getPathStat(name);
if (st)
{
time = st->st_mtime;
if (type == ST_FILE)
{
if (st->st_size > UINT32_MAX) size = UINT32_MAX;
else size = (uint32_t)st->st_size;
}
}
time_t days = time / 86400;
time_t left = time - (days * 86400);
time_t mins = left / 60;
time_t secs = left - (mins * 60);
time_t ticks = secs * 50;
days -= 2922; // Days between 1970 - 01 - 01 and 1978 - 01 - 01
if (days < 0) days = 0;
res->disk_key = SWAP_INT(disk_key);
res->entry_type = SWAP_INT(type);
res->size = SWAP_INT(size);
res->protection = 0;
res->date[0] = SWAP_INT(days);
res->date[1] = SWAP_INT(mins);
res->date[2] = SWAP_INT(ticks);
res->file_name[0] = strlen(fn);
strcpy(res->file_name + 1, fn);
sz_res = sizeof(ExamineObjectResponse) + strlen(fn);
ret = 0;
}
break;
case ACTION_FINDINPUT: // MODE_OLDFILE
case ACTION_FINDOUTPUT: // MODE_NEWFILE
case ACTION_FINDUPDATE: // MODE_READWRITE
{
dbg_print("> ACTION_FIND\n");
FindXxxRequest *req = (FindXxxRequest*)reqres_buffer;
FindXxxResponse *res = (FindXxxResponse*)reqres_buffer;
sz_res = sizeof(FindXxxResponse);
char *name = find_path(SWAP_INT(req->key), req->name + 1);
if (!name[0])
{
ret = ERROR_DIR_NOT_FOUND;
break;
}
if (PathIsDir(name))
{
ret = ERROR_OBJECT_WRONG_TYPE;
break;
}
uint32_t key = get_fp();
open_file_handles[key] = {};
int mode = O_RDWR;
if (rtype == MODE_NEWFILE) mode = O_RDWR | O_CREAT | O_TRUNC;
if (rtype == MODE_READWRITE) mode = O_RDWR | O_CREAT;
ret = FileOpenEx(&open_file_handles[key], name, mode);
if (!ret)
{
open_file_handles.erase(key);
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
res->arg1 = SWAP_INT(key);
ret = 0;
}
break;
case ACTION_READ:
{
dbg_print("> ACTION_READ\n");
ReadRequest *req = (ReadRequest*)reqres_buffer;
ReadResponse *res = (ReadResponse*)reqres_buffer;
sz_res = sizeof(ReadResponse);
uint32_t key = SWAP_INT(req->arg1);
if (open_file_handles.find(key) == open_file_handles.end())
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t length = SWAP_INT(req->length);
length = FileReadAdv(&open_file_handles[key], shmem + DATA_BUFFER, length);
res->actual = SWAP_INT(length);
ret = 0;
}
break;
case ACTION_WRITE:
{
dbg_print("> ACTION_WRITE\n");
WriteRequest *req = (WriteRequest*)reqres_buffer;
WriteResponse *res = (WriteResponse*)reqres_buffer;
sz_res = sizeof(WriteResponse);
uint32_t key = SWAP_INT(req->arg1);
if (open_file_handles.find(key) == open_file_handles.end())
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t length = SWAP_INT(req->length);
length = FileWriteAdv(&open_file_handles[key], shmem + DATA_BUFFER, length);
res->actual = SWAP_INT(length);
ret = 0;
}
break;
case ACTION_SEEK:
{
dbg_print("> ACTION_SEEK\n");
SeekRequest *req = (SeekRequest*)reqres_buffer;
SeekResponse *res = (SeekResponse*)reqres_buffer;
sz_res = sizeof(SeekResponse);
uint32_t key = SWAP_INT(req->arg1);
if (open_file_handles.find(key) == open_file_handles.end())
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t old_pos = open_file_handles[key].offset;
uint32_t new_pos = SWAP_INT(req->new_pos);
uint32_t mode = SWAP_INT(req->mode);
int origin = SEEK_SET;
if (mode == OFFSET_CURRENT) origin = SEEK_CUR;
if (mode == OFFSET_END) origin = SEEK_END;
ret = FileSeek(&open_file_handles[key], new_pos, origin);
dbg_print(" mode: %d\n", mode);
dbg_print(" old_pos: %d\n", old_pos);
dbg_print(" new_pos: %d\n", new_pos);
if (!ret)
{
ret = ERROR_SEEK_ERROR;
break;
}
res->old_pos = SWAP_INT(old_pos);
ret = 0;
}
break;
case ACTION_END:
{
dbg_print("> ACTION_END\n");
EndRequest *req = (EndRequest*)reqres_buffer;
uint32_t key = SWAP_INT(req->arg1);
if (open_file_handles.find(key) != open_file_handles.end())
{
FileClose(&open_file_handles[key]);
open_file_handles.erase(key);
}
ret = 0;
}
break;
case ACTION_DELETE_OBJECT:
{
dbg_print("> ACTION_DELETE_OBJECT\n");
DeleteObjectRequest *req = (DeleteObjectRequest*)reqres_buffer;
char *name = find_path(SWAP_INT(req->key), req->name + 1);
if (name[0])
{
if (has_locks(name))
{
ret = ERROR_OBJECT_IN_USE;
break;
}
if (PathIsDir(name))
{
ret = DirDelete(name) ? 0 : ERROR_DIRECTORY_NOT_EMPTY;
break;
}
if (FileExists(name))
{
ret = FileDelete(name) ? 0 : ERROR_OBJECT_NOT_FOUND;
break;
}
}
ret = ERROR_OBJECT_NOT_FOUND;
}
break;
case ACTION_RENAME_OBJECT:
{
dbg_print("> ACTION_RENAME_OBJECT\n");
RenameObjectRequest *req = (RenameObjectRequest*)reqres_buffer;
strncpy(buf, req->name, req->name_len);
buf[req->name_len] = 0;
uint32_t key = SWAP_INT(req->key);
char *cp1 = find_path(key, buf);
if (!cp1[0])
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
if (!FileExists(cp1) && !PathIsDir(cp1))
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
strcpy(buf, cp1);
key = SWAP_INT(req->target_dir);
char *cp2 = find_path(key, req->name + req->name_len);
if (!cp2[0])
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
if (FileExists(cp2) || PathIsDir(cp2))
{
ret = ERROR_OBJECT_EXISTS;
break;
}
strcpy(buf, getFullPath(buf));
if (rename(buf, getFullPath(cp2)))
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
ret = 0;
}
break;
case ACTION_CREATE_DIR:
{
dbg_print("> ACTION_CREATE_DIR\n");
CreateDirRequest *req = (CreateDirRequest*)reqres_buffer;
CreateDirResponse *res = (CreateDirResponse*)reqres_buffer;
sz_res = sizeof(CreateDirResponse);
char *name = find_path(SWAP_INT(req->key), req->name + 1);
if (!FileCreatePath(name))
{
ret = ERROR_OBJECT_NOT_FOUND;
break;
}
uint32_t key = add_lock(SHARED_LOCK, name);
res->key = SWAP_INT(key);
ret = 0;
}
break;
case ACTION_DISK_INFO:
case ACTION_INFO:
{
dbg_print("> ACTION_INFO\n");
DiskInfoResponse *res = (DiskInfoResponse*)reqres_buffer;
sz_res = sizeof(DiskInfoResponse);
uint32_t total = 10;
uint32_t used = 1;
struct statvfs st;
if (!statvfs(getFullPath(basepath), &st))
{
uint64_t sz = st.f_bsize * st.f_blocks;
uint64_t avail = st.f_bsize * st.f_bavail;
total = sz / 512;
used = (sz - avail) / 512;
}
res->total = SWAP_INT(total);
res->used = SWAP_INT(used);
ret = 0;
}
break;
case ACTION_SET_PROTECT:
{
dbg_print("> ACTION_SET_PROTECT unimplemented\n");
ret = 0;
}
break;
case ACTION_SET_COMMENT:
{
dbg_print("> ACTION_SET_COMMENT unimplemented\n");
ret = 0;
}
break;
}
int success = ret ? 0 : 1;
reqres->success = SWAP_INT(success);
reqres->error_code = SWAP_INT(ret);
dbg_print("error: %d\n", ret);
dbg_hexdump(shmem + REQUEST_BUFFER, sz_res, 0);
dbg_print("\n");
return sz_res;
}
static void share_init()
{
int fd;
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) return;
shmem = (uint8_t*)mmap(0, SHMEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHMEM_ADDR);
close(fd);
if (shmem == (uint8_t *)-1) printf("minimig_setup_shmem: Unable to mmap(/dev/mem)\n");
return;
}
void minimig_share_poll()
{
if (!shmem)
{
share_init();
}
else if(shmem != (uint8_t *)-1)
{
static uint32_t old_req_id = 0;
uint32_t req_id = *(uint32_t*)(shmem + REQUEST_FLG);
if ((uint16_t)old_req_id != (uint16_t)req_id)
{
dbg_print("new req: %08X\n", req_id);
old_req_id = req_id;
if (((req_id>>16) & 0xFFFF) == 0x5AA5 && ((req_id - 77) & 0xFF) == ((req_id >> 8) & 0xFF))
{
process_request(shmem + REQUEST_BUFFER);
*(uint16_t*)(shmem + REQUEST_FLG + 2) = (uint16_t)req_id;
}
}
}
}
void minimig_share_reset()
{
open_file_handles.clear();
locks.clear();
next_fp = 1;
next_key = 1;
}

View File

@@ -0,0 +1,10 @@
#ifndef __MINIMIG_SHARE_H__
#define __MINIMIG_SHARE_H__
#include <stdint.h>
void minimig_share_poll();
void minimig_share_reset();
#endif

View File

@@ -2165,13 +2165,14 @@ void user_io_poll()
}
}
if (!rtc_timer || CheckTimer(rtc_timer))
{
// Update once per minute should be enough
rtc_timer = GetTimer(60000);
send_rtc(1);
}
minimig_share_poll();
}
if (core_type == CORE_TYPE_8BIT && !is_menu())