diff --git a/support/minimig/miminig_fs_messages.h b/support/minimig/miminig_fs_messages.h index d65f906..fc73fcc 100644 --- a/support/minimig/miminig_fs_messages.h +++ b/support/minimig/miminig_fs_messages.h @@ -28,6 +28,7 @@ #define ACTION_DISK_TYPE 32 #define ACTION_DISK_CHANGE 33 #define ACTION_SET_DATE 34 +#define ACTION_SAME_LOCK 40 #define ACTION_SCREEN_MODE 994 #define ACTION_READ_RETURN 1001 #define ACTION_WRITE_RETURN 1002 @@ -38,6 +39,7 @@ #define ACTION_SEEK 1008 #define ACTION_TRUNCATE 1022 #define ACTION_WRITE_PROTECT 1023 +#define ACTION_EXAMINE_FH 1034 #define ERROR_NO_FREE_STORE 103 #define ERROR_TASK_TABLE_FULL 105 @@ -74,6 +76,10 @@ #define SHARED_LOCK -2 #define EXCLUSIVE_LOCK -1 +#define LOCK_DIFFERENT -1 +#define LOCK_SAME 0 +#define LOCK_SAME_VOLUME 1 + #define MODE_OLDFILE 1005 #define MODE_NEWFILE 1006 #define MODE_READWRITE 1004 @@ -356,6 +362,42 @@ struct SetCommentResponse long error_code; }; +struct SameLockRequest +{ + long sz; + long type; + long key1; + long key2; +}; + +struct SameLockResponse +{ + long sz; + long success; + long error_code; +}; + +struct ExamineFhRequest +{ + long sz; + long type; + long arg1; +}; + +struct ExamineFhResponse +{ + 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 DiskInfoRequest { long sz; diff --git a/support/minimig/minimig_share.cpp b/support/minimig/minimig_share.cpp index 6c974aa..14898ea 100644 --- a/support/minimig/minimig_share.cpp +++ b/support/minimig/minimig_share.cpp @@ -27,6 +27,10 @@ static uint8_t *shmem = 0; #define REQUEST_BUFFER 4 // ~512B #define DATA_BUFFER 0x1000 // 4KB +// Must match device name in MountList and volume name from MiSTerFileSystem +#define DEVICE_NAME "SHARE" +#define VOLUME_NAME "MiSTer" + //#define DEBUG #ifdef DEBUG @@ -124,7 +128,12 @@ static char* find_path(uint32_t key, const char *name) const char* p = strchr(name, ':'); if (p) { - key = 0; + size_t root_len = p - name; + + // Don't use lock for relative path if the name contains our root + if (root_len == 0 || !strncasecmp(name, DEVICE_NAME, root_len) || !strncasecmp(name, VOLUME_NAME, root_len)) + key = 0; + name = p + 1; } @@ -218,6 +227,21 @@ static char* find_path(uint32_t key, const char *name) return str; } +static void fill_date(time_t time, int date[3]) +{ + 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; + + date[0] = SWAP_INT(days); + date[1] = SWAP_INT(mins); + date[2] = SWAP_INT(ticks); +} + static int process_request(void *reqres_buffer) { static char buf[1024]; @@ -465,21 +489,11 @@ static int process_request(void *reqres_buffer) } } - 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); + fill_date(time, res->date); res->file_name[0] = strlen(fn); strcpy(res->file_name + 1, fn); @@ -489,6 +503,65 @@ static int process_request(void *reqres_buffer) } break; + case ACTION_EXAMINE_FH: + { + dbg_print("> ACTION_EXAMINE_FH\n"); + ExamineFhRequest *req = (ExamineFhRequest*)reqres_buffer; + ExamineFhResponse *res = (ExamineFhResponse*)reqres_buffer; + sz_res = sizeof(ExamineFhResponse); + + uint32_t key = SWAP_INT(req->arg1); + dbg_print(" key: %d\n", key); + + if (open_file_handles.find(key) == open_file_handles.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + const char *fn = open_file_handles[key].name; + int disk_key = 666; + int type = 0; + time_t time = 0; + uint32_t size = 0; + + struct stat64 st; + if (fstat64(fileno(open_file_handles[key].filp), &st) == 0) + { + time = st.st_mtime; + if (st.st_mode & S_IFDIR) type = ST_USERDIR; + else + { + type = ST_FILE; + if (st.st_size > UINT32_MAX) size = UINT32_MAX; + else size = (uint32_t)st.st_size; + } + } + else + { + dbg_print("Couldn't stat %s: %d\n", fn, errno); + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + dbg_print(" fn: %s\n", fn); + dbg_print(" size: %lld\n", open_file_handles[key].size); + dbg_print(" type: %d\n", type); + + res->disk_key = SWAP_INT(disk_key); + res->entry_type = SWAP_INT(type); + res->size = SWAP_INT(size); + res->protection = 0; + fill_date(time, res->date); + + res->file_name[0] = strlen(fn); + strcpy(res->file_name + 1, fn); + + sz_res = sizeof(ExamineFhResponse) + strlen(fn); + ret = 0; + } + break; + case ACTION_FINDINPUT: // MODE_OLDFILE case ACTION_FINDOUTPUT: // MODE_NEWFILE case ACTION_FINDUPDATE: // MODE_READWRITE @@ -502,7 +575,7 @@ static int process_request(void *reqres_buffer) if (!name[0]) { - ret = ERROR_DIR_NOT_FOUND; + ret = ERROR_OBJECT_NOT_FOUND; break; } @@ -591,10 +664,10 @@ static int process_request(void *reqres_buffer) break; } - uint32_t old_pos = open_file_handles[key].offset; + int old_pos = open_file_handles[key].offset; - uint32_t new_pos = SWAP_INT(req->new_pos); - uint32_t mode = SWAP_INT(req->mode); + int new_pos = SWAP_INT(req->new_pos); + int mode = SWAP_INT(req->mode); int origin = SEEK_SET; if (mode == OFFSET_CURRENT) origin = SEEK_CUR; @@ -694,6 +767,16 @@ static int process_request(void *reqres_buffer) ret = ERROR_OBJECT_NOT_FOUND; break; } + + strcpy(buf, getFullPath(buf)); + const char *fp2 = getFullPath(cp2); + + // Identical match; do nothing + if (!strcmp(buf, fp2)) + { + ret = 0; + break; + } if (FileExists(cp2, 0) || PathIsDir(cp2, 0)) { @@ -701,8 +784,7 @@ static int process_request(void *reqres_buffer) break; } - strcpy(buf, getFullPath(buf)); - if (rename(buf, getFullPath(cp2))) + if (rename(buf, fp2)) { ret = ERROR_OBJECT_NOT_FOUND; break; @@ -772,6 +854,30 @@ static int process_request(void *reqres_buffer) ret = 0; } break; + + case ACTION_SAME_LOCK: + { + dbg_print("> ACTION_SAME_LOCK\n"); + SameLockRequest *req = (SameLockRequest*)reqres_buffer; + + uint32_t key1 = SWAP_INT(req->key1); + uint32_t key2 = SWAP_INT(req->key2); + + if ((locks.find(key1) == locks.end()) || (locks.find(key2) == locks.end())) + { + ret = LOCK_DIFFERENT; + break; + } + + if (locks[key1].path == locks[key2].path) + { + ret = LOCK_SAME; + break; + } + + ret = LOCK_SAME_VOLUME; + } + break; } int success = ret ? 0 : 1;