diff --git a/LICENSE.TXT b/LICENSE.TXT index 6c8ae97..8982931 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -1,5 +1,5 @@ ## License -### 2014-2020 webMAN MOD / ps3netsrv +### 2014-2022 webMAN MOD / ps3netsrv webMAN MOD is a FREE software and all its components (ps3netsrv included) are distributed and protected under GNU General Public License version 3 (GPL v3) @@ -14,6 +14,17 @@ It is NOT permitted to distribute modified versions with the same name of this software. A similar name or misleading name should NOT be used, to avoid confusion about the origin or the version in use. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + For futher information about GPL v3, refer to: https://www.gnu.org/licenses/gpl-3.0.en.html @@ -37,7 +48,7 @@ the software. -(C) 2010-2020 multiMAN / webMAN by DeanK +(C) 2010-2022 multiMAN / webMAN / sMAN / sLaunch / prepNTFS by DeanK Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/Makefile b/Makefile index 6068617..128e7e3 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ OS = windows BUILD_TYPE = release_static OUTPUT := ps3netsrv -OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/File.o src/VIsoFile.o +OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/mem.o src/File.o src/VIsoFile.o CFLAGS = -Wall -Wno-format -I./include -std=gnu99 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL CPPFLAGS += -Wall -Wno-format -I./include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL @@ -15,7 +15,7 @@ CPPFLAGS += -Wall -Wno-format -I./include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_B #CFLAGS += -DNOSSL #CPPFLAGS +=-DNOSSL -#OBJS = src/main.o src/compat.o src/File.o src/VIsoFile.o +#OBJS = src/main.o src/compat.o src/mem.o src/File.o src/VIsoFile.o LDFLAGS = -L. LIBS = -lstdc++ diff --git a/Makefile.linux b/Makefile.linux index 7f8dfc2..dedc626 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -2,7 +2,7 @@ OS = linux BUILD_TYPE = release_static OUTPUT := ps3netsrv -OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/File.o src/VIsoFile.o +OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/mem.o src/File.o src/VIsoFile.o CFLAGS = -Wall -I./include -std=gnu99 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL CPPFLAGS += -Wall -I./include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL @@ -12,7 +12,7 @@ CPPFLAGS += -Doff64_t=off_t #CFLAGS += -DNOSSL #CPPFLAGS +=-DNOSSL -#OBJS = src/main.o src/compat.o src/File.o src/VIsoFile.o +#OBJS = src/main.o src/compat.o src/mem.o src/File.o src/VIsoFile.o LDFLAGS = -L. LIBS = -lstdc++ diff --git a/Makefile.macos b/Makefile.macos index 8569a43..c4f86bb 100644 --- a/Makefile.macos +++ b/Makefile.macos @@ -2,7 +2,7 @@ OS = macos BUILD_TYPE = release OUTPUT := ps3netsrv -OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/File.o src/VIsoFile.o +OBJS = src/main.o src/padlock.o src/aes.o src/compat.o src/mem.o src/File.o src/VIsoFile.o CFLAGS = -Wall -I./include -std=gnu99 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL CPPFLAGS += -Wall -I./include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DPOLARSSL @@ -12,7 +12,7 @@ CPPFLAGS += -Doff64_t=off_t #CFLAGS += -DNOSSL #CPPFLAGS +=-DNOSSL -#OBJS = src/main.o src/compat.o src/File.o src/VIsoFile.o +#OBJS = src/main.o src/compat.o src/mem.o src/File.o src/VIsoFile.o LDFLAGS = -L. LIBS = -lstdc++ diff --git a/README.md b/README.md index b77dd60..38b5102 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,38 @@ To build ps3netsrv using the bundled POLARSSL library instead of mbed TLS and wi On Linux this will statically link ps3netsrv. +``` +sudo apt-get update +sudo apt-get install make +sudo apt-get install g++ +./Make.sh +``` + ## Docker Container Docker Engine enables applications built in containers packages to run anywhere consistently on any infrastructure. Docker container packages for ps3netsrv are available at: https://hub.docker.com/search?q=ps3netsrv + +## Other ports / forks +Docker container: +https://github.com/shawly/docker-ps3netsrv + +Xcode (macOS / Linux / FreeBSD 10): +https://github.com/klahjn/ps3netsrvXCODE +https://github.com/klahjn/macOSPS3NetServerGUI + +Java / Android: +https://github.com/jhonathanc/ps3netsrv-android + +Google Go: +https://github.com/xakep666/ps3netsrv-go + +ps3netsrv modified for encrypted (3k3y/redump) isos: +http://forum.redump.org/topic/14472 + +ps3netsrv modified for multiMAN: +http://deanbg.com/ps3netsrv.zip + +Original ps3netsrv by Cobra for Linux / Windows: +https://github.com/Joonie86/Cobra-7.00/tree/master/446/PC/ps3netsrv diff --git a/include/File.h b/include/File.h index 737fb86..bb11998 100644 --- a/include/File.h +++ b/include/File.h @@ -78,7 +78,7 @@ class File : public AbstractFile file_t fp[64]; int64_t last_seek; int8_t is_multipart; - int64_t part_size; + uint64_t part_size; int8_t index; public: diff --git a/include/VIsoFile.h b/include/VIsoFile.h index dc88877..add25ed 100644 --- a/include/VIsoFile.h +++ b/include/VIsoFile.h @@ -89,9 +89,13 @@ class VIsoFile : public AbstractFile off64_t padAreaStart; off64_t padAreaSize; + file_t fd; file_stat_t st; + char *lastPath; + void reset(void); + void fd_reset(void); DirList *getParent(DirList *dirList); bool isDirectChild(DirList *dir, DirList *parentCheck); diff --git a/include/common.h b/include/common.h index 6297f03..908d8a4 100644 --- a/include/common.h +++ b/include/common.h @@ -11,7 +11,7 @@ #endif #ifndef _OS_WINDOWS -#include +#include #define __BIG_ENDIAN__ (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #endif #if __BIG_ENDIAN__ diff --git a/include/compat.h b/include/compat.h index c19f4af..c9943a3 100644 --- a/include/compat.h +++ b/include/compat.h @@ -89,6 +89,8 @@ ssize_t write_file(file_t fd, void *buf, size_t nbyte); int64_t seek_file(file_t fd, int64_t offset, int whence); int fstat_file(file_t fd, file_stat_t *fs); int stat_file(const char *path, file_stat_t *fs); +void _memset(void *m, size_t n); +void _memcpy(void *dst, void *src, size_t n); #ifdef __cplusplus } diff --git a/include/mem.h b/include/mem.h new file mode 100644 index 0000000..d1c10bb --- /dev/null +++ b/include/mem.h @@ -0,0 +1,18 @@ +#ifndef __MEM_H__ +#define __MEM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void _memset(void *m, size_t n); +void _memcpy(void *dst, void *src, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* __MEM_H__ */ diff --git a/meson.build b/meson.build index 94fe48e..0c67823 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,7 @@ project('ps3netsrv', ['c', 'cpp'], ps3netsrv_inc = include_directories('include') ps3netsrv_src = files( + 'src/mem.c', 'src/compat.c', 'src/File.cpp', 'src/main.cpp', diff --git a/src/File.cpp b/src/File.cpp index 3808b4f..3481f9c 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -321,16 +321,16 @@ ssize_t File::read(void *buf, size_t nbyte) // read encrypted-3k3yredump-isos by NvrBst // int64_t read_position = seek(0, SEEK_CUR); - ssize_t ret = read_file(fd, buf, nbyte); - - add_last_seek(ret); - if (read_position < 0LL) { printf("ERROR: read > enc > seek: Returning decrypted data.\n"); - return ret; + return FAILED; } + ssize_t ret = read_file(fd, buf, nbyte); + + add_last_seek(ret); + // If this is a 3k3y iso, and the 0xF70 data is being requests by ps3, we should null it out. if ((enc_type_ == kDiscType3k3yDec) || (enc_type_ == kDiscType3k3yEnc)) { @@ -339,7 +339,7 @@ ssize_t File::read(void *buf, size_t nbyte) // Zero out the 0xF70 - 0x1070 overlap. unsigned char *bufb = reinterpret_cast(buf); unsigned char *buf_overlap_start = read_position < 0xF70LL ? bufb + 0xF70LL - read_position : bufb; - memset(buf_overlap_start, 0x00, read_position + ret < 0x1070LL ? ret - (buf_overlap_start - bufb) : 0x100 - (buf_overlap_start - bufb)); + _memset(buf_overlap_start, read_position + ret < 0x1070LL ? ret - (buf_overlap_start - bufb) : 0x100 - (buf_overlap_start - bufb)); } // If it's a dec image then return, else go on to the decryption logic. @@ -437,7 +437,7 @@ int File::fstat(file_stat_t *fs) return fstat_file(fd, fs); // fstat multi part (2015 AV) - return sum of size of iso parts - int64_t size = 0; + uint64_t size = 0; file_stat_t statbuf; for(uint8_t i = 0; i < is_multipart; i++) diff --git a/src/VIsoFile.cpp b/src/VIsoFile.cpp index d1057af..59d5768 100644 --- a/src/VIsoFile.cpp +++ b/src/VIsoFile.cpp @@ -73,7 +73,7 @@ static uint8_t strncpy_upper(char *s1, const char *s2, uint8_t n) static char *createPath(uint16_t dlen, const char *dir, uint16_t flen, const char *file) { - char *ret = new char[dlen + flen + 2]; + char *ret = new char[dlen + flen + 2]; if(!ret) return NULL; sprintf(ret, "%s/%s", dir, file); return ret; } @@ -350,7 +350,7 @@ static int parse_param_sfo(file_t fd, const char *field, char *field_value, int return -2; } - memset(mem, 0, len + 16); + _memset(mem, len + 16); seek_file(fd, 0, SEEK_SET); read_file(fd, mem, len); @@ -396,8 +396,7 @@ static bool get_title_id(const char *dir, char *title_id) char sfo_path[MAX_PATH]; snprintf(sfo_path, sizeof(sfo_path) - 1, "%s/PS3_GAME/PARAM.SFO", dir); - file_t fd; - fd = open_file(sfo_path, O_RDONLY); + file_t fd = open_file(sfo_path, O_RDONLY); if (!FD_OK(fd)) { fprintf(stderr, "Cannot find %s\n", sfo_path); @@ -443,6 +442,8 @@ static int select_files(const struct dirent2 *entry) return true; } +// VIsoFile class: AbstractFile + VIsoFile::VIsoFile(bool ps3Mode) { this->ps3Mode = ps3Mode; @@ -464,6 +465,9 @@ VIsoFile::VIsoFile(bool ps3Mode) totalSize = 0; padAreaStart = 0; padAreaSize = 0; + + fd = 0; + lastPath = NULL; } VIsoFile::~VIsoFile() @@ -473,6 +477,8 @@ VIsoFile::~VIsoFile() reset(); } +// private + void VIsoFile::reset(void) { if (fsBuf) @@ -550,6 +556,16 @@ void VIsoFile::reset(void) totalSize = 0; padAreaStart = 0; padAreaSize = 0; + + fd_reset(); +} + +void VIsoFile::fd_reset(void) +{ + close_file(fd); + + fd = 0; + lastPath = NULL; } DirList *VIsoFile::getParent(DirList *dirList) @@ -607,7 +623,7 @@ Iso9660DirectoryRecord *VIsoFile::findDirRecord(const char *dirName, Iso9660Dire uint32_t pos = 0; uint8_t strCheckSize; - memset(strCheck, 0, 256); + _memset(strCheck, 256); if (!joliet) { @@ -657,7 +673,7 @@ uint8_t *VIsoFile::buildPathTable(bool msb, bool joliet, size_t *retSize) uint8_t *p; int i = 0; - memset(tempBuf, 0, tempBufSize); + _memset(tempBuf, tempBufSize); p = tempBuf; dirList = rootList; while ((dirList) && (i < 65536)) @@ -715,7 +731,7 @@ uint8_t *VIsoFile::buildPathTable(bool msb, bool joliet, size_t *retSize) *retSize = (p - tempBuf); uint8_t *ret = new uint8_t[*retSize]; if(!ret) return 0; - memcpy(ret, tempBuf, *retSize); + _memcpy(ret, tempBuf, *retSize); return ret; } @@ -733,7 +749,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) if (!parent) return false; - memset(tempBuf, 0, tempBufSize); + _memset(tempBuf, tempBufSize); // . entry record = (Iso9660DirectoryRecord *)p; @@ -794,7 +810,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) { uint32_t offs; record = (Iso9660DirectoryRecord *)malloc(SECTOR_SIZE); if(!record) return false; - memset(record, 0, SECTOR_SIZE); + _memset(record, SECTOR_SIZE); record->lsbStart = LE32(lba); record->msbStart = BE32(lba); @@ -897,7 +913,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) return false; } - memcpy(p, record, record->len_dr); + _memcpy(p, record, record->len_dr); p += record->len_dr; free(record); } @@ -912,7 +928,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) { uint32_t offs; record = (Iso9660DirectoryRecord *)malloc(SECTOR_SIZE); - memset(record, 0, SECTOR_SIZE); + _memset(record, SECTOR_SIZE); if (stat_file(tempList->path, &statbuf) < 0) { @@ -957,7 +973,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) return false; } - memcpy(p, record, record->len_dr); + _memcpy(p, record, record->len_dr); p += record->len_dr; free(record); } @@ -976,7 +992,7 @@ bool VIsoFile::buildContent(DirList *dirList, bool joliet) p = new uint8_t[size]; if(!p) {if(record) free(record); return false;} - memcpy(p, tempBuf, size); + _memcpy(p, tempBuf, size); record = (Iso9660DirectoryRecord *)p; record->lsbDataLength = LE32(size); @@ -1112,6 +1128,7 @@ bool VIsoFile::build(const char *inDir) int count; int idx = 0; uint16_t flen; + bool error = false; rootList->path = dupString(inDir, dlen); if(rootList->path == NULL) return false; rootList->path_len = dlen; @@ -1132,20 +1149,28 @@ bool VIsoFile::build(const char *inDir) dlen = dirList->full_len; for (int i = 0; i < count; i++) { - #ifdef WIN32 - flen = dirs[i]->d_namlen; - #else - flen = strlen(dirs[i]->d_name); - #endif - tail = tail->next = new DirList; - tail->path = createPath(dlen, dirList->path, flen, dirs[i]->d_name); - tail->path_len = dlen; - tail->full_len = dlen + flen + 1; - tail->content = NULL; - tail->contentJoliet = NULL; - tail->idx = idx++; - tail->fileList = NULL; - tail->next = NULL; + if (!error) + { + #ifdef WIN32 + flen = dirs[i]->d_namlen; + #else + flen = strlen(dirs[i]->d_name); + #endif + tail = tail->next = new DirList; + tail->path = createPath(dlen, dirList->path, flen, dirs[i]->d_name); + if(tail->path) + { + tail->path_len = dlen; + tail->full_len = dlen + flen + 1; + tail->content = NULL; + tail->contentJoliet = NULL; + tail->idx = idx++; + tail->fileList = NULL; + tail->next = NULL; + } + else + error = true; + } free(dirs[i]); } @@ -1159,7 +1184,6 @@ bool VIsoFile::build(const char *inDir) { struct dirent2 **files; FileList *fileList = NULL; - bool error = false; uint16_t dlen; count = scandir(dirList->path, &files, select_files, alphasort); @@ -1206,24 +1230,26 @@ bool VIsoFile::build(const char *inDir) fileList = fileList->next = new FileList; } + error = true; + if(fileList) { fileList->path = createPath(dlen, dirList->path, flen, files[i]->d_name); - fileList->path_len = dlen; - fileList->file_len = flen; - fileList->multipart = multipart; - fileList->next = NULL; - - if (getFileSizeAndProcessMultipart(fileList->path, &fileList->size, multipart, dlen + flen)) + if(fileList->path) { - fileList->rlba = filesSizeSectors; - filesSizeSectors += bytesToSectors(fileList->size); + fileList->path_len = dlen; + fileList->file_len = flen; + fileList->multipart = multipart; + fileList->next = NULL; + + if (getFileSizeAndProcessMultipart(fileList->path, &fileList->size, multipart, dlen + flen)) + { + fileList->rlba = filesSizeSectors; + filesSizeSectors += bytesToSectors(fileList->size); + error = false; + } } - else - error = true; } - else - error = true; } free(files[i]); @@ -1285,7 +1311,7 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) time_t t = time(NULL); // Write first 16 empty sectors - memset(fsBuf, 0, 0x8000); + _memset(fsBuf, 0x8000); if (ps3Mode) { @@ -1312,7 +1338,7 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) // Generate and write iso pvd pvd = (Iso9660PVD *)(fsBuf + 0x8000); - memset(pvd, 0, SECTOR_SIZE); + _memset(pvd, SECTOR_SIZE); pvd->VDType = 1; memcpy(pvd->VSStdId, "CD001", sizeof(pvd->VSStdId)); @@ -1355,12 +1381,12 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) // Write joliet pvd pvd = (Iso9660PVD *)(fsBuf + 0x8800); - memset(pvd, 0, SECTOR_SIZE); + _memset(pvd, SECTOR_SIZE); pvd->VDType = 2; memcpy(pvd->VSStdId, "CD001", sizeof(pvd->VSStdId)); pvd->VSStdVersion = 1; - memset(pvd->systemIdentifier, 0, sizeof(pvd->systemIdentifier)); + _memset(pvd->systemIdentifier, sizeof(pvd->systemIdentifier)); utf8_to_ucs2((const unsigned char *)volumeName, (uint16_t *)pvd->volumeIdentifier, sizeof(pvd->volumeIdentifier) / 2); pvd->lsbVolumeSpaceSize = LE32(volumeSize); pvd->msbVolumeSpaceSize = BE32(volumeSize); @@ -1388,31 +1414,31 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) // Write sector 18 p = fsBuf + 0x9000; - memset(p, 0, SECTOR_SIZE); + _memset(p, SECTOR_SIZE); p[0] = 0xFF; memcpy(p + 1, "CD001", 5); // Write empty sector 19 p = fsBuf + 0x9800; - memset(p, 0, SECTOR_SIZE); + _memset(p, SECTOR_SIZE); // Write pathTableL p = fsBuf + 0xA000; - memset(p, 0, bytesToSectors(pathTableSize) * SECTOR_SIZE); - memcpy(p, pathTableL, pathTableSize); + _memset(p, bytesToSectors(pathTableSize) * SECTOR_SIZE); + _memcpy(p, pathTableL, pathTableSize); // Write pathTableM p += (bytesToSectors(pathTableSize) * SECTOR_SIZE); - memcpy(p, pathTableM, pathTableSize); + _memcpy(p, pathTableM, pathTableSize); // Write pathTableJolietL p += (bytesToSectors(pathTableSize) * SECTOR_SIZE); - memset(p, 0, bytesToSectors(pathTableSizeJoliet) * SECTOR_SIZE); - memcpy(p, pathTableJolietL, pathTableSizeJoliet); + _memset(p, bytesToSectors(pathTableSizeJoliet) * SECTOR_SIZE); + _memcpy(p, pathTableJolietL, pathTableSizeJoliet); // Write pathTableJolietM p += (bytesToSectors(pathTableSizeJoliet) * SECTOR_SIZE); - memcpy(p, pathTableJolietM, pathTableSizeJoliet); + _memcpy(p, pathTableJolietM, pathTableSizeJoliet); p += (bytesToSectors(pathTableSizeJoliet) * SECTOR_SIZE); @@ -1429,7 +1455,7 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) dirList = rootList; while (dirList) { - memcpy(p, dirList->content, dirList->contentSize); + _memcpy(p, dirList->content, dirList->contentSize); p += dirList->contentSize; dirList = dirList->next; } @@ -1438,7 +1464,7 @@ void VIsoFile::write(const char *volumeName, const char *gameCode) dirList = rootList; while (dirList) { - memcpy(p, dirList->contentJoliet, dirList->contentJolietSize); + _memcpy(p, dirList->contentJoliet, dirList->contentJolietSize); p += dirList->contentJolietSize; dirList = dirList->next; } @@ -1486,12 +1512,14 @@ bool VIsoFile::generate(const char *inDir, const char *volumeName, const char *g delete[] fsBuf; fsBuf = new uint8_t[fsBufSize]; if(!fsBuf) return false; - memset(fsBuf, 0, fsBufSize); + _memset(fsBuf, fsBufSize); write(volumeName, gameCode); return true; } +// public + int VIsoFile::open(const char *path, int flags) { if(!path) @@ -1573,6 +1601,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) if(!buf) { printf("viso error: no read buffer\n"); + fd_reset(); return FAILED; } @@ -1584,6 +1613,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) if (!fsBuf) { printf("viso error: file error in read\n"); + fd_reset(); return FAILED; } @@ -1598,6 +1628,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) else if (vFilePtr < 0) { printf("viso error: pointer error in read\n"); + fd_reset(); return FAILED; } @@ -1605,7 +1636,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) { // Read FS structure from RAM to_read = MIN(fsBufSize - vFilePtr, remaining); - memcpy(p, fsBuf + vFilePtr, to_read); + _memcpy(p, fsBuf + vFilePtr, to_read); remaining -= to_read; r += to_read; @@ -1640,31 +1671,37 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) if (vFilePtr < fEnd) { - file_t fd; - int64_t this_r; + if(lastPath != fileList->path) + { + close_file(fd); + lastPath = fileList->path; - to_read = MIN((uint64_t)(fileList->size - (vFilePtr - fStart)), remaining); - fd = open_file(fileList->path, O_RDONLY); + fd = open_file(fileList->path, O_RDONLY); - if (!FD_OK(fd)) - { - fprintf(stderr, "VISO: file %s cannot be opened!\n", fileList->path); - return r; + if (!FD_OK(fd)) + { + fprintf(stderr, "VISO: file %s cannot be opened!\n", fileList->path); + fd_reset(); + return r; + } } + to_read = MIN((uint64_t)(fileList->size - (vFilePtr - fStart)), remaining); + seek_file(fd, vFilePtr - fStart, SEEK_SET); - this_r = read_file(fd, p, to_read); - close_file(fd); + int64_t this_r = read_file(fd, p, to_read); if (this_r < 0) { fprintf(stderr, "VISO: read_file failed on %s\n", fileList->path); + fd_reset(); return r; } if (this_r != (int64_t)to_read) { fprintf(stderr, "VISO: read on file %s returned less data than expected (file modified?)\n", fileList->path); + fd_reset(); return r; } @@ -1678,7 +1715,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) { // This is a zero area after the file to fill the sector to_read = MIN((uint64_t)((fEndSector - fEnd) - (vFilePtr - fEnd)), remaining); - memset(p, 0, to_read); + _memset(p, to_read); remaining -= to_read; r += to_read; @@ -1706,7 +1743,7 @@ ssize_t VIsoFile::read(void *buf, size_t nbyte) else return r; // to_read = 0; - memset(p, 0, to_read); + _memset(p, to_read); remaining -= to_read; r += to_read; diff --git a/src/compat.c b/src/compat.c index 9d4370a..f66d36d 100644 --- a/src/compat.c +++ b/src/compat.c @@ -1,4 +1,5 @@ #include "compat.h" +#include "mem.h" static const int FAILED = -1; static const int SUCCEEDED = 0; diff --git a/src/main.cpp b/src/main.cpp index 091238d..f82b545 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,7 +24,7 @@ static const int NONE = -1; #include "File.h" #include "VIsoFile.h" -#define BUFFER_SIZE (3 * 1048576) +#define BUFFER_SIZE (4 * 1048576) #define MAX_CLIENTS 5 #define MAX_ENTRIES 4096 @@ -58,6 +58,7 @@ typedef struct _client_t struct in_addr ip_addr; thread_t thread; uint16_t CD_SECTOR_SIZE; + int subdirs; } client_t; static client_t clients[MAX_CLIENTS]; @@ -85,7 +86,7 @@ static int initialize_socket(uint16_t port) int flag = 1; if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof(flag)) < 0) { - DPRINTF("Error in setsockopt(REUSEADDR): %d\n", get_network_error()); + printf("ERROR in setsockopt(REUSEADDR): %d\n", get_network_error()); closesocket(s); return FAILED; } @@ -96,13 +97,13 @@ static int initialize_socket(uint16_t port) if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - DPRINTF("Error in bind: %d\n", get_network_error()); + printf("ERROR in bind: %d\n", get_network_error()); return FAILED; } if(listen(s, 1) < 0) { - DPRINTF("Error in listen: %d\n", get_network_error()); + printf("ERROR in listen: %d\n", get_network_error()); return FAILED; } @@ -136,9 +137,9 @@ static int recv_all(int s, void *buf, int size) } #endif -static char *normalize_path(char *path, int8_t del_last_slash) +static int normalize_path(char *path, int8_t del_last_slash) { - if(!path) return path; + if(!path) return 0; char *p = path; @@ -148,10 +149,27 @@ static char *normalize_path(char *path, int8_t del_last_slash) p++; } - if((p > path) && (*(p - 1) == '\r')) *(--p) = 0; // remove last CR if found + while(p > path) + { + if(*(p - 1) == '\r') + *(--p) = 0; // remove last CR if found + else + break; + } + + if(del_last_slash) + while(p > path) + { + if(*(p - 1) == '/') + *(--p) = 0; // remove last slash + else + break; + } - if(del_last_slash) {if(p > path) {--p; if(*p == '/') *p = 0;}} - return path; + if(p > path) + return (p - path); + + return 0; } static int initialize_client(client_t *client) @@ -161,7 +179,7 @@ static int initialize_client(client_t *client) client->buf = (uint8_t *)malloc(BUFFER_SIZE); if(!client->buf) { - DPRINTF("Memory allocation error!\n"); + printf("CRITICAL: Memory allocation error!\n"); return FAILED; } @@ -171,6 +189,8 @@ static int initialize_client(client_t *client) client->dirpath = NULL; client->connected = 1; client->CD_SECTOR_SIZE = 2352; + client->subdirs = 0; + return SUCCEEDED; } @@ -212,46 +232,42 @@ static void finalize_client(client_t *client) client->dirpath = NULL; client->connected = 0; client->CD_SECTOR_SIZE = 2352; + client->subdirs = 0; memset(client, 0, sizeof(client_t)); } static char *translate_path(char *path, int *viso) { - char *p; - if(!path) return NULL; - normalize_path(path, false); + size_t path_len = normalize_path(path, false); if(path[0] != '/') { - DPRINTF("path must start by '/'. Path received: %s\n", path); + printf("ERROR: path must start by '/'. Path received: %s\n", path); if(path) free(path); return NULL; } // check unsecure path - p = strstr(path, "/.."); - if(!p) p = strstr(path, "\\.."); // not needed if path is normalized - if( p) + char *p = strstr(path, "/.."); + if(p) { p += 3; - if ((*p == 0) || (*p == '/') || (*p == '\\')) + if ((*p == 0) || (*p == '/')) { - DPRINTF("The path \"%s\" is unsecure!\n", path); + printf("ERROR: The path \"%s\" is unsecure!\n", path); if(path) free(path); return NULL; } } - size_t path_len = strlen(path); - p = (char *)malloc(MAX_PATH_LEN + root_len + path_len + 1); if(!p) { - printf("Memory allocation error\n"); + printf("CRITICAL: Memory allocation error\n"); if(path) free(path); return NULL; @@ -290,10 +306,9 @@ static char *translate_path(char *path, int *viso) if(stat_file(p, &st) < 0) { // get path only (without file name) - //char *dir_name = p; char lnk_file[MAX_LINK_LEN]; - char *sep = NULL; size_t p_len = root_len + path_len; + char *filename = NULL; for(size_t i = p_len; i >= root_len; i--) { @@ -303,22 +318,20 @@ static char *translate_path(char *path, int *viso) sprintf(lnk_file, "%s.INI", p); // e.g. /BDISO.INI if (i < p_len) p[i] = '/'; - if(stat_file(lnk_file, &st) >= 0) {sep = p + i; break;} + if(stat_file(lnk_file, &st) >= 0) {filename = p + i; break;} } } - if(sep) + if(filename) { - file_t fd; - fd = open_file(lnk_file, O_RDONLY); + file_t fd = open_file(lnk_file, O_RDONLY); if (FD_OK(fd)) { // read INI - memset(lnk_file, 0, MAX_LINK_LEN); + _memset(lnk_file, MAX_LINK_LEN); read_file(fd, lnk_file, MAX_LINK_LEN); close_file(fd); - char *filename = sep; int flen = strlen(filename); // check all paths in INI @@ -359,21 +372,22 @@ static char *translate_path(char *path, int *viso) if(path) free(path); - return normalize_path(p, false); + normalize_path(p, false); + + return p; } static int64_t calculate_directory_size(char *path) { int64_t result = 0; - DIR *d; struct dirent *entry; //DPRINTF("Calculate %s\n", path); - //file_stat_t st; - //if(stat_file(path, &st) < 0) return FAILED; + file_stat_t st; + if(stat_file(path, &st) < 0) return FAILED; - d = opendir(path); + DIR *d = opendir(path); if(!d) return FAILED; @@ -398,7 +412,6 @@ static int64_t calculate_directory_size(char *path) //DPRINTF("name: %s\n", entry->d_name); sprintf(newpath + path_len, "%s", entry->d_name); - file_stat_t st; if(stat_file(newpath, &st) < 0) { DPRINTF("calculate_directory_size: stat failed on %s\n", newpath); @@ -434,26 +447,26 @@ static int64_t calculate_directory_size(char *path) static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) { - file_stat_t st; netiso_open_result result; + char *filepath = NULL; - uint16_t fp_len; - uint16_t rlen; int ret = FAILED, viso = VISO_NONE; + uint16_t rlen; + uint16_t fp_len; + + result.file_size = BE64(NONE); + result.mtime = BE64(0); if(!client->buf) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); goto send_result; // return FAILED; } - result.file_size = NONE; - result.mtime = BE64(0); - fp_len = BE16(cmd->fp_len); if(fp_len == 0) { - DPRINTF("ERROR: invalid path length for open command\n"); + printf("ERROR: invalid path length for open command\n"); goto send_result; // return FAILED; } @@ -461,7 +474,7 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); if(!filepath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); goto send_result; // return FAILED; } @@ -470,7 +483,7 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) if(rlen != fp_len) { - DPRINTF("recv failed, getting filename for open: %d %d\n", rlen, get_network_error()); + printf("ERROR: open failed receiving filename: %d %d\n", rlen, get_network_error()); goto send_result; // return FAILED; } @@ -489,7 +502,7 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) filepath = translate_path(filepath, &viso); if(!filepath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); goto send_result; // return FAILED; } @@ -518,6 +531,7 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) } else { + file_stat_t st; if(client->ro_file->fstat(&st) < 0) { printf("fstat error on \"%s\" (viso=%d)\n", filepath + rlen, viso); @@ -557,13 +571,13 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) ret = SUCCEEDED; } - } -#ifdef WIN32 - DPRINTF("File size: %I64x\n", st.file_size); -#else - DPRINTF("File size: %llx\n", (long long unsigned int)st.file_size); -#endif + #ifdef WIN32 + DPRINTF("File size: %I64x\n", st.file_size); + #else + DPRINTF("File size: %llx\n", (long long unsigned int)st.file_size); + #endif + } send_result: @@ -580,15 +594,12 @@ static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) static int process_read_file_critical(client_t *client, netiso_read_file_critical_cmd *cmd) { - uint64_t offset; - uint32_t remaining; - - offset = BE64(cmd->offset); - remaining = BE32(cmd->num_bytes); - if ((!client->ro_file) || (!client->buf)) return FAILED; + uint64_t offset = BE64(cmd->offset); + uint32_t remaining = BE32(cmd->num_bytes); + #ifdef WIN32 DPRINTF("Read %I64x %x\n", (long long unsigned int)offset, remaining); #else @@ -614,14 +625,14 @@ static int process_read_file_critical(client_t *client, netiso_read_file_critica ssize_t read_ret = client->ro_file->read(client->buf, read_size); if ((read_ret < 0) || (static_cast(read_ret) != read_size)) { - DPRINTF("read_file failed on read file critical command!\n"); + printf("ERROR: read_file failed on read file critical command!\n"); return FAILED; } int send_ret = send(client->s, (char *)client->buf, read_size, 0); if ((send_ret < 0) || (static_cast(send_ret) != read_size)) { - DPRINTF("send failed on read file critical command!\n"); + printf("ERROR: send failed on read file critical command!\n"); return FAILED; } @@ -633,32 +644,28 @@ static int process_read_file_critical(client_t *client, netiso_read_file_critica static int process_read_cd_2048_critical_cmd(client_t *client, netiso_read_cd_2048_critical_cmd *cmd) { - uint64_t offset; - uint32_t sector_count; - uint8_t *buf; + if ((!client->ro_file) || (!client->buf)) + return FAILED; - offset = BE32(cmd->start_sector)*(client->CD_SECTOR_SIZE); - sector_count = BE32(cmd->sector_count); + uint64_t offset = BE32(cmd->start_sector)*(client->CD_SECTOR_SIZE); + uint32_t sector_count = BE32(cmd->sector_count); DPRINTF("Read CD 2048 (%i) %x %x\n", client->CD_SECTOR_SIZE, BE32(cmd->start_sector), sector_count); - if ((!client->ro_file) || (!client->buf)) - return FAILED; - if((sector_count * 2048) > BUFFER_SIZE) { // This is just to save some uneeded code. PS3 will never request such a high number of sectors - DPRINTF("This situation wasn't expected, too many sectors read!\n"); + printf("ERROR: Too many sectors read!\n"); return FAILED; } - buf = client->buf; + uint8_t *buf = client->buf; for (uint32_t i = 0; i < sector_count; i++) { client->ro_file->seek(offset + 24, SEEK_SET); if(client->ro_file->read(buf, 2048) != 2048) { - DPRINTF("read_file failed on read cd 2048 critical command!\n"); + printf("ERROR: read_file failed on read cd 2048 critical command!\n"); return FAILED; } @@ -669,7 +676,7 @@ static int process_read_cd_2048_critical_cmd(client_t *client, netiso_read_cd_20 int send_ret = send(client->s, (char *)client->buf, sector_count * 2048, 0); if ((send_ret < 0) || (static_cast(send_ret) != (sector_count * 2048))) { - DPRINTF("send failed on read cd 2048 critical command!\n"); + printf("ERROR: send failed on read cd 2048 critical command!\n"); return FAILED; } @@ -678,29 +685,24 @@ static int process_read_cd_2048_critical_cmd(client_t *client, netiso_read_cd_20 static int process_read_file_cmd(client_t *client, netiso_read_file_cmd *cmd) { - uint64_t offset; - uint32_t read_size; - int32_t bytes_read; + int32_t bytes_read = NONE; netiso_read_file_result result; - offset = BE64(cmd->offset); - read_size = BE32(cmd->num_bytes); + uint32_t read_size = BE32(cmd->num_bytes); + uint64_t offset = BE64(cmd->offset); if ((!client->ro_file) || (!client->buf)) { - bytes_read = NONE; goto send_result_read_file; } if(read_size > BUFFER_SIZE) { - bytes_read = NONE; goto send_result_read_file; } if(client->ro_file->seek(offset, SEEK_SET) < 0) { - bytes_read = NONE; goto send_result_read_file; } @@ -716,13 +718,13 @@ static int process_read_file_cmd(client_t *client, netiso_read_file_cmd *cmd) if(send(client->s, (char *)&result, sizeof(result), 0) != 4) { - DPRINTF("send failed on send result (read file)\n"); + printf("ERROR: send failed on send result (read file)\n"); return FAILED; } if((bytes_read > 0) && (send(client->s, (char *)client->buf, bytes_read, 0) != bytes_read)) { - DPRINTF("send failed on read file!\n"); + printf("ERROR: send failed on read file!\n"); return FAILED; } @@ -732,86 +734,93 @@ static int process_read_file_cmd(client_t *client, netiso_read_file_cmd *cmd) static int process_create_cmd(client_t *client, netiso_create_cmd *cmd) { netiso_create_result result; - char *filepath; - uint16_t fp_len; - int ret; + result.create_result = BE32(NONE); - fp_len = BE16(cmd->fp_len); + int created = FAILED; + uint16_t fp_len = BE16(cmd->fp_len); - filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); + char *filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); if(!filepath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } filepath[fp_len] = 0; - ret = recv_all(client->s, (void *)filepath, fp_len); + int ret = recv_all(client->s, (void *)filepath, fp_len); if(ret != fp_len) { - DPRINTF("recv failed, getting filename for create: %d %d\n", ret, get_network_error()); - free(filepath); - return FAILED; + printf("ERROR: recv failed, getting filename for create: %d %d\n", ret, get_network_error()); + goto send_result; } filepath = translate_path(filepath, NULL); if(!filepath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); - return FAILED; + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); + goto send_result; } - DPRINTF("create %s\n", filepath); - if(client->wo_file) { delete client->wo_file; } + // filepath is a directory / closing file + file_stat_t st; + if((stat_file(filepath, &st) >= 0) && ((st.mode & S_IFDIR) == S_IFDIR)) + { + client->wo_file = NULL; + goto send_result; + } + + DPRINTF("create %s\n", filepath); client->wo_file = new File(); if(client->wo_file->open(filepath, O_WRONLY|O_CREAT|O_TRUNC) < 0) { - DPRINTF("create error on \"%s\"\n", filepath); - result.create_result = BE32(NONE); + printf("ERROR: create error on \"%s\"\n", filepath); delete client->wo_file; client->wo_file = NULL; } else { - result.create_result = BE32(0); + result.create_result = BE32(SUCCEEDED); + created = SUCCEEDED; } +send_result: + free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("create, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: create, send result error: %d %d\n", ret, get_network_error()); return FAILED; } - return SUCCEEDED; + return created; } static int process_write_file_cmd(client_t *client, netiso_write_file_cmd *cmd) { - uint32_t write_size; - int32_t bytes_written; netiso_write_file_result result; + result.bytes_written = (int32_t)BE32(NONE); - write_size = BE32(cmd->num_bytes); + int bytes_written; + uint32_t write_size = BE32(cmd->num_bytes); + int file_written = FAILED; if ((!client->wo_file) || (!client->buf)) { - bytes_written = NONE; goto send_result_write_file; } if(write_size > BUFFER_SIZE) { - DPRINTF("data to write (%i) is larger than buffer size (%i)", write_size, BUFFER_SIZE); - return FAILED; + printf("ERROR: data to write (%i) is larger than buffer size (%i)", write_size, BUFFER_SIZE); + goto send_result_write_file; } //DPRINTF("write size: %d\n", write_size); @@ -821,51 +830,47 @@ static int process_write_file_cmd(client_t *client, netiso_write_file_cmd *cmd) int ret = recv_all(client->s, (void *)client->buf, write_size); if ((ret < 0) || (static_cast(ret) != write_size)) { - DPRINTF("recv failed on write file: %d %d\n", ret, get_network_error()); - return FAILED; + printf("ERROR: recv failed on write file: %d %d\n", ret, get_network_error()); + goto send_result_write_file; } } bytes_written = client->wo_file->write(client->buf, write_size); - if(bytes_written < 0) + if(bytes_written >= 0) { - bytes_written = NONE; + result.bytes_written = (int32_t)BE32(bytes_written); + file_written = SUCCEEDED; } send_result_write_file: - result.bytes_written = (int32_t)BE32(bytes_written); - if(send(client->s, (char *)&result, sizeof(result), 0) != 4) { - DPRINTF("send failed on send result (read file)\n"); + printf("ERROR: send failed on send result (read file)\n"); return FAILED; } - return SUCCEEDED; + return file_written; } static int process_delete_file_cmd(client_t *client, netiso_delete_file_cmd *cmd) { netiso_delete_file_result result; - char *filepath; - uint16_t fp_len; - int ret; - fp_len = BE16(cmd->fp_len); + uint16_t fp_len = BE16(cmd->fp_len); - filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); + char *filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); if(!filepath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } filepath[fp_len] = 0; - ret = recv_all(client->s, (void *)filepath, fp_len); + int ret = recv_all(client->s, (void *)filepath, fp_len); if(ret != fp_len) { - DPRINTF("recv failed, getting filename for delete file: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting filename for delete file: %d %d\n", ret, get_network_error()); free(filepath); return FAILED; } @@ -873,7 +878,7 @@ static int process_delete_file_cmd(client_t *client, netiso_delete_file_cmd *cmd filepath = translate_path(filepath, NULL); if(!filepath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -888,7 +893,7 @@ static int process_delete_file_cmd(client_t *client, netiso_delete_file_cmd *cmd ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("delete, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: delete, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -898,24 +903,21 @@ static int process_delete_file_cmd(client_t *client, netiso_delete_file_cmd *cmd static int process_mkdir_cmd(client_t *client, netiso_mkdir_cmd *cmd) { netiso_mkdir_result result; - char *dirpath; - uint16_t dp_len; - int ret; - dp_len = BE16(cmd->dp_len); + uint16_t dp_len = BE16(cmd->dp_len); - dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); + char *dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); if(!dirpath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } dirpath[dp_len] = 0; - ret = recv_all(client->s, (void *)dirpath, dp_len); + int ret = recv_all(client->s, (void *)dirpath, dp_len); if(ret != dp_len) { - DPRINTF("recv failed, getting dirname for mkdir: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting dirname for mkdir: %d %d\n", ret, get_network_error()); free(dirpath); return FAILED; } @@ -923,7 +925,7 @@ static int process_mkdir_cmd(client_t *client, netiso_mkdir_cmd *cmd) dirpath = translate_path(dirpath, NULL); if(!dirpath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -942,7 +944,7 @@ static int process_mkdir_cmd(client_t *client, netiso_mkdir_cmd *cmd) ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("open dir, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: open dir, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -952,24 +954,21 @@ static int process_mkdir_cmd(client_t *client, netiso_mkdir_cmd *cmd) static int process_rmdir_cmd(client_t *client, netiso_rmdir_cmd *cmd) { netiso_rmdir_result result; - char *dirpath; - uint16_t dp_len; - int ret; - dp_len = BE16(cmd->dp_len); + uint16_t dp_len = BE16(cmd->dp_len); - dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); + char *dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); if(!dirpath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } dirpath[dp_len] = 0; - ret = recv_all(client->s, (void *)dirpath, dp_len); + int ret = recv_all(client->s, (void *)dirpath, dp_len); if(ret != dp_len) { - DPRINTF("recv failed, getting dirname for rmdir: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting dirname for rmdir: %d %d\n", ret, get_network_error()); free(dirpath); return FAILED; } @@ -977,7 +976,7 @@ static int process_rmdir_cmd(client_t *client, netiso_rmdir_cmd *cmd) dirpath = translate_path(dirpath, NULL); if(!dirpath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -992,7 +991,7 @@ static int process_rmdir_cmd(client_t *client, netiso_rmdir_cmd *cmd) ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("open dir, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: open dir, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -1002,32 +1001,31 @@ static int process_rmdir_cmd(client_t *client, netiso_rmdir_cmd *cmd) static int process_open_dir_cmd(client_t *client, netiso_open_dir_cmd *cmd) { netiso_open_dir_result result; - char *dirpath; - uint16_t dp_len; - int ret; - dp_len = BE16(cmd->dp_len); + uint16_t dp_len = BE16(cmd->dp_len); - dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); + char *dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); if(!dirpath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } dirpath[dp_len] = 0; - ret = recv_all(client->s, (void *)dirpath, dp_len); + int ret = recv_all(client->s, (void *)dirpath, dp_len); if(ret != dp_len) { - DPRINTF("recv failed, getting dirname for open dir: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting dirname for open dir: %d %d\n", ret, get_network_error()); free(dirpath); return FAILED; } + client->subdirs = strstr(dirpath, "//") ? 1 : 0; + dirpath = translate_path(dirpath, NULL); if(!dirpath) { - printf("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -1045,7 +1043,11 @@ static int process_open_dir_cmd(client_t *client, netiso_open_dir_cmd *cmd) client->dirpath = NULL; normalize_path(dirpath, true); - client->dir = opendir(dirpath); + + file_stat_t st; + if(stat_file(dirpath, &st) >= 0) + client->dir = opendir(dirpath); + if(!client->dir) { //printf("open dir error on \"%s\"\n", dirpath); @@ -1059,7 +1061,7 @@ static int process_open_dir_cmd(client_t *client, netiso_open_dir_cmd *cmd) client->dirpath = dirpath; printf("open dir %s\n", dirpath + rlen); strcat(dirpath, "/"); - result.open_result = BE32(0); + result.open_result = BE32(SUCCEEDED); } if(!client->dirpath) @@ -1070,7 +1072,7 @@ static int process_open_dir_cmd(client_t *client, netiso_open_dir_cmd *cmd) ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("open dir, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: open dir, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -1081,9 +1083,11 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm { (void) cmd; char *path = NULL; + file_stat_t st; struct dirent *entry = NULL; size_t d_name_len = 0; + netiso_read_dir_entry_result result_v1; netiso_read_dir_entry_result_v2 result_v2; @@ -1110,6 +1114,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm goto send_result_read_dir; } + // ignore parent dir & files larger than MAX_FILE_LEN while ((entry = readdir(client->dir))) { if(IS_PARENT_DIR(entry->d_name)) continue; @@ -1127,6 +1132,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm { closedir(client->dir); if(client->dirpath) free(client->dirpath); + client->dir = NULL; client->dirpath = NULL; @@ -1144,7 +1150,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm path = (char *)malloc(MAX_PATH_LEN + strlen(client->dirpath) + d_name_len + 2); if(!path) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); goto send_result_read_dir; } @@ -1155,6 +1161,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm { closedir(client->dir); if(client->dirpath) free(client->dirpath); + client->dir = NULL; client->dirpath = NULL; @@ -1218,7 +1225,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm { if(send(client->s, (char *)&result_v1, sizeof(result_v1), 0) != sizeof(result_v1)) { - DPRINTF("send error on read dir entry (%d)\n", get_network_error()); + printf("ERROR: send error on read dir entry (%d)\n", get_network_error()); return FAILED; } } @@ -1226,7 +1233,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm { if(send(client->s, (char *)&result_v2, sizeof(result_v2), 0) != sizeof(result_v2)) { - DPRINTF("send error on read dir entry (%d)\n", get_network_error()); + printf("ERROR: send error on read dir entry (%d)\n", get_network_error()); return FAILED; } } @@ -1236,7 +1243,7 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm int send_ret = send(client->s, (char *)entry->d_name, d_name_len, 0); if ((send_ret < 0) || (static_cast(send_ret) != d_name_len)) { - DPRINTF("send file name error on read dir entry (%d)\n", get_network_error()); + printf("ERROR: send file name error on read dir entry (%d)\n", get_network_error()); return FAILED; } } @@ -1244,46 +1251,34 @@ static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cm return SUCCEEDED; } -static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd) +static void process_read_dir(netiso_read_dir_result_data *dir_entries, char *path, size_t dirpath_len, size_t path_len, int max_items, int *nitems, int subdirs) { - (void) cmd; - int64_t items = 0; - - netiso_read_dir_result result; - memset(&result, 0, sizeof(result)); - - netiso_read_dir_result_data *dir_entries = (netiso_read_dir_result_data *) malloc(sizeof(netiso_read_dir_result_data) * MAX_ENTRIES); - memset(dir_entries, 0, sizeof(netiso_read_dir_result_data) * MAX_ENTRIES); - - char *path = (char*)malloc(MAX_PATH_LEN + root_len + strlen(client->dirpath + root_len) + MAX_FILE_LEN + 2); - - if ((!client->dir) || (!client->dirpath) || (!dir_entries) || (!path)) - { - result.dir_size = (0); - goto send_result_read_dir_cmd; - } + int items = *nitems; file_stat_t st; struct dirent *entry; + size_t d_name_len; - size_t d_name_len, dirpath_len; - dirpath_len = sprintf(path, "%s/", client->dirpath); + normalize_path(path, true); + DIR *dir2 = opendir(path); + strcat(path, "/"); + size_t dir2path_len = strlen(path); - // list dir - while ((entry = readdir(client->dir))) + if(dir2) { - if(IS_PARENT_DIR(entry->d_name)) continue; + while ((entry = readdir(dir2))) + { + if(IS_PARENT_DIR(entry->d_name)) continue; - #ifdef WIN32 - d_name_len = entry->d_namlen; - #else - d_name_len = strlen(entry->d_name); - #endif + #ifdef WIN32 + d_name_len = entry->d_namlen; + #else + d_name_len = strlen(entry->d_name); + #endif + if(dir2path_len + d_name_len >= path_len) continue; - if(IS_RANGE(d_name_len, 1, MAX_FILE_LEN)) - { - sprintf(path + dirpath_len, "%s", entry->d_name); + sprintf(path + dir2path_len, "%s", entry->d_name); if(stat_file(path, &st) < 0) { @@ -1294,11 +1289,16 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd st.ctime = 0; } - if(!st.mtime) {st.mtime = st.ctime; - if(!st.mtime) st.mtime = st.atime;} - if((st.mode & S_IFDIR) == S_IFDIR) { + if(subdirs) + { + if(subdirs < 2) process_read_dir(dir_entries, path, dirpath_len, path_len, max_items, &items, 2); + + path[dir2path_len] = '\0'; + continue; + } + dir_entries[items].file_size = (0); dir_entries[items].is_directory = 1; } @@ -1308,22 +1308,84 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd dir_entries[items].is_directory = 0; } - sprintf(dir_entries[items].name, "%s", entry->d_name); + if(!st.mtime) {st.mtime = st.ctime; + if(!st.mtime) st.mtime = st.atime;} + dir_entries[items].mtime = BE64(st.mtime); + if(subdirs) + sprintf(dir_entries[items].name, "%s", path + dirpath_len); + else + sprintf(dir_entries[items].name, "%s", entry->d_name); + + path[dir2path_len] = '\0'; + items++; - if(items >= MAX_ENTRIES) break; + if(items >= max_items) break; } + closedir(dir2); dir2 = NULL; + } + *nitems = items; +} + +static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd) +{ + (void) cmd; + + int items = 0; + int max_items = MAX_ENTRIES; + size_t path_len = 0; + + char *path = NULL; + netiso_read_dir_result_data *dir_entries = NULL; + + netiso_read_dir_result result; + memset(&result, 0, sizeof(result)); + result.dir_size = BE64(0); + + if ((!client->dir) || (!client->dirpath)) + { + goto send_result_read_dir_cmd; + } + + for (; max_items >= 0x10; max_items -= 0x10) + { + dir_entries = (netiso_read_dir_result_data *) malloc(sizeof(netiso_read_dir_result_data) * max_items); + if (dir_entries) break; + } + + if (!dir_entries) + { + goto send_result_read_dir_cmd; + } + + path_len = MAX_PATH_LEN + root_len + strlen(client->dirpath + root_len) + MAX_FILE_LEN + 2; + + path = (char*)malloc(path_len); + + if (!path) + { + goto send_result_read_dir_cmd; } + _memset(dir_entries, sizeof(netiso_read_dir_result_data) * max_items); + + file_stat_t st; + + size_t dirpath_len; + dirpath_len = sprintf(path, "%s", client->dirpath); + + // list dir + process_read_dir(dir_entries, path, dirpath_len, path_len, max_items, &items, client->subdirs); + if(client->dir) {closedir(client->dir); client->dir = NULL;} #ifdef MERGE_DIRS - unsigned int slen; + char *p; + size_t slen; char *ini_file; // get INI file for directory - char *p; p = client->dirpath; slen = dirpath_len - 1; //strlen(p); ini_file = path; @@ -1345,7 +1407,7 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd { // read INI char lnk_file[MAX_LINK_LEN]; - memset(lnk_file, 0, MAX_LINK_LEN); + _memset(lnk_file, MAX_LINK_LEN); read_file(fd, lnk_file, MAX_LINK_LEN); close_file(fd); @@ -1361,61 +1423,10 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd // check dir exists if(stat_file(dir_path, &st) >= 0) { - DIR *dir = opendir(dir_path); + printf("-> %s\n", dir_path); + dirpath_len = (strncmp(dir_path, root_directory, root_len) == 0) ? root_len : 0; - if(dir) - { - printf("-> %s\n", dir_path); - dirpath_len = sprintf(path, "%s/", dir_path); - - // list dir - while ((entry = readdir(dir))) - { - if(IS_PARENT_DIR(entry->d_name)) continue; - - #ifdef WIN32 - d_name_len = entry->d_namlen; - #else - d_name_len = strlen(entry->d_name); - #endif - - if(IS_RANGE(d_name_len, 1, MAX_FILE_LEN)) - { - sprintf(path + dirpath_len, "%s", entry->d_name); - - if(stat_file(path, &st) < 0) - { - st.file_size = 0; - st.mode = S_IFDIR; - st.mtime = 0; - st.atime = 0; - st.ctime = 0; - } - - if(!st.mtime) {st.mtime = st.ctime; - if(!st.mtime) st.mtime = st.atime;} - - if((st.mode & S_IFDIR) == S_IFDIR) - { - dir_entries[items].file_size = (0); - dir_entries[items].is_directory = 1; - } - else - { - dir_entries[items].file_size = BE64(st.file_size); - dir_entries[items].is_directory = 0; - } - - sprintf(dir_entries[items].name, "%s", entry->d_name); - dir_entries[items].mtime = BE64(st.mtime); - - items++; - if(items >= MAX_ENTRIES) break; - } - } - - closedir(dir); dir = NULL; - } + process_read_dir(dir_entries, dir_path, dirpath_len, path_len, max_items, &items, client->subdirs); } // read next line @@ -1437,7 +1448,7 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd if(items > 0) { - if(send(client->s, (const char*)dir_entries, (sizeof(netiso_read_dir_result_data)*items), 0) != (int)(sizeof(netiso_read_dir_result_data)*items)) + if(send(client->s, (const char*)dir_entries, (sizeof(netiso_read_dir_result_data) * items), 0) != (int)(sizeof(netiso_read_dir_result_data) * items)) { if(dir_entries) free(dir_entries); return FAILED; @@ -1451,24 +1462,21 @@ static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) { netiso_stat_result result; - char *filepath; - uint16_t fp_len; - int ret; - fp_len = BE16(cmd->fp_len); + uint16_t fp_len = BE16(cmd->fp_len); - filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); + char *filepath = (char *)malloc(MAX_PATH_LEN + fp_len + 1); if(!filepath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } filepath[fp_len] = 0; - ret = recv_all(client->s, (char *)filepath, fp_len); + int ret = recv_all(client->s, (char *)filepath, fp_len); if(ret != fp_len) { - DPRINTF("recv failed, getting filename for stat: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting filename for stat: %d %d\n", ret, get_network_error()); free(filepath); return FAILED; } @@ -1476,7 +1484,7 @@ static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) filepath = translate_path(filepath, NULL); if(!filepath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -1484,8 +1492,8 @@ static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) DPRINTF("stat %s\n", filepath); if((stat_file(filepath, &st) < 0) && (!strstr(filepath, "/is_ps3_compat1/"))) { - DPRINTF("stat error on \"%s\"\n", filepath); - result.file_size = NONE; + DPRINTF("ERROR: stat error on \"%s\"\n", filepath); + result.file_size = BE64(NONE); } else { @@ -1510,7 +1518,7 @@ static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("stat, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: stat, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -1520,24 +1528,21 @@ static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) static int process_get_dir_size_cmd(client_t *client, netiso_get_dir_size_cmd *cmd) { netiso_get_dir_size_result result; - char *dirpath; - uint16_t dp_len; - int ret; - dp_len = BE16(cmd->dp_len); + uint16_t dp_len = BE16(cmd->dp_len); - dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); + char *dirpath = (char *)malloc(MAX_PATH_LEN + dp_len + 1); if(!dirpath) { - DPRINTF("CRITICAL: memory allocation error\n"); + printf("CRITICAL: memory allocation error\n"); return FAILED; } dirpath[dp_len] = 0; - ret = recv_all(client->s, (char *)dirpath, dp_len); + int ret = recv_all(client->s, (char *)dirpath, dp_len); if(ret != dp_len) { - DPRINTF("recv failed, getting dirname for get_dir_size: %d %d\n", ret, get_network_error()); + printf("ERROR: recv failed, getting dirname for get_dir_size: %d %d\n", ret, get_network_error()); free(dirpath); return FAILED; } @@ -1545,7 +1550,7 @@ static int process_get_dir_size_cmd(client_t *client, netiso_get_dir_size_cmd *c dirpath = translate_path(dirpath, NULL); if(!dirpath) { - DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); + printf("ERROR: Path cannot be translated. Connection with this client will be aborted.\n"); return FAILED; } @@ -1557,7 +1562,7 @@ static int process_get_dir_size_cmd(client_t *client, netiso_get_dir_size_cmd *c ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { - DPRINTF("get_dir_size, send result error: %d %d\n", ret, get_network_error()); + printf("ERROR: get_dir_size, send result error: %d %d\n", ret, get_network_error()); return FAILED; } @@ -1571,9 +1576,8 @@ void *client_thread(void *arg) for(;;) { netiso_cmd cmd; - int ret; + int ret = recv_all(client->s, (void *)&cmd, sizeof(cmd)); - ret = recv_all(client->s, (void *)&cmd, sizeof(cmd)); if(ret != sizeof(cmd)) { break; @@ -1585,14 +1589,14 @@ void *client_thread(void *arg) ret = process_read_file_critical(client, (netiso_read_file_critical_cmd *)&cmd); break; - case NETISO_CMD_READ_CD_2048_CRITICAL: - ret = process_read_cd_2048_critical_cmd(client, (netiso_read_cd_2048_critical_cmd *)&cmd); - break; - case NETISO_CMD_READ_FILE: ret = process_read_file_cmd(client, (netiso_read_file_cmd *)&cmd); break; + case NETISO_CMD_READ_CD_2048_CRITICAL: + ret = process_read_cd_2048_critical_cmd(client, (netiso_read_cd_2048_critical_cmd *)&cmd); + break; + case NETISO_CMD_WRITE_FILE: ret = process_write_file_cmd(client, (netiso_write_file_cmd *)&cmd); break; @@ -1642,7 +1646,7 @@ void *client_thread(void *arg) break; default: - DPRINTF("Unknown command received: %04X\n", BE16(cmd.opcode)); + printf("ERROR: Unknown command received: %04X\n", BE16(cmd.opcode)); ret = FAILED; } @@ -1659,15 +1663,15 @@ void *client_thread(void *arg) int main(int argc, char *argv[]) { int s; + uint16_t port = NETISO_PORT; uint32_t whitelist_start = 0; uint32_t whitelist_end = 0; - uint16_t port = NETISO_PORT; get_normal_color(); // Show build number set_white_text(); - printf("ps3netsrv build 20200708"); + printf("ps3netsrv build 20220421"); set_red_text(); printf(" (mod by aldostools)\n"); @@ -1676,7 +1680,7 @@ int main(int argc, char *argv[]) #ifndef WIN32 if(sizeof(off_t) < 8) { - DPRINTF("off_t too small!\n"); + printf("ERROR: off_t too small!\n"); goto exit_error; } #endif @@ -1766,9 +1770,8 @@ int main(int argc, char *argv[]) } // Show shared directory - normalize_path(root_directory, true); + root_len = normalize_path(root_directory, true); printf("Path: %s\n\n", root_directory); - root_len = strlen(root_directory); // Check for root directory if(strcmp(root_directory, "/") == 0) @@ -1978,7 +1981,7 @@ int main(int argc, char *argv[]) else { // Check whitelist range - if(whitelist_start != 0) + if(whitelist_start) { uint32_t ip = BE32(addr.sin_addr.s_addr); diff --git a/src/mem.c b/src/mem.c new file mode 100644 index 0000000..e92a779 --- /dev/null +++ b/src/mem.c @@ -0,0 +1,33 @@ +#include "mem.h" + +void _memset(void *m, size_t n) +{ + uint8_t p = n & 7; + + n >>= 3; + uint64_t *s = (uint64_t *) m; + while (n--) *s++ = 0LL; + + if(p) + { + char *c = (char *) s; + while (p--) *c++ = '\0'; + } +} + +void _memcpy(void *dst, void *src, size_t n) +{ + uint8_t p = n & 7; + + n >>= 3; + uint64_t *d = (uint64_t *) dst; + uint64_t *s = (uint64_t *) src; + while (n--) *d++ = *s++; + + if(p) + { + char *m = (char *) d; + char *c = (char *) s; + while (p--) *m++ = *c++; + } +}