diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..d59ddb8 --- /dev/null +++ b/client/Makefile @@ -0,0 +1,162 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := ps3load +BUILD := build +SOURCES := source +INCLUDES := include +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +DEBUGFLAGS := +CFLAGS := $(DEBUGFLAGS) -Wall -O3\ + +CFLAGS += $(INCLUDE) + +LDFLAGS = $(DEBUGFLAGS) + +UNAME := $(shell uname -s) + +ifeq ($(strip $(PS3DEV)),) + ifeq ($(strip $(DEVKITPS3)),) + export PS3DEV := /usr/local/ps3dev + else + export PS3DEV := $(DEVKITPS3) + endif +endif + +ifneq (,$(findstring MINGW,$(UNAME))) + EXEEXT := .exe + PLATFORM_LIBS := -static -lws2_32 +endif + +ifneq (,$(findstring Darwin,$(shell uname -s))) + SDK := $(shell xcrun --show-sdk-path) + OSX_MIN := $(shell defaults read $(shell xcrun --show-sdk-platform-path)/Info MinimumSDKVersion 2> /dev/null || 10.4) + OSXCFLAGS := -mmacosx-version-min=$(OSX_MIN) -isysroot $(SDK) + OSXCXXFLAGS := $(OSXCFLAGS) + CXXFLAGS += -fvisibility=hidden + LDFLAGS += -mmacosx-version-min=$(OSX_MIN) -Wl,-syslibroot,$(SDK) +endif + +ifneq (,$(findstring SunOS,$(UNAME))) + PLATFORM_LIBS := -lresolv -lsocket -lnsl +endif + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := $(PLATFORM_LIBS) -lz +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + + +export OUTPUT := $(CURDIR)/$(TARGET)$(EXEEXT) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) + +export CC := gcc +export CXX := g++ +export AR := ar +export OBJCOPY := objcopy + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT) + +#--------------------------------------------------------------------------------- +install: $(BUILD) + @echo Installing $(TARGET)$(EXEEXT) + @[ -d $(PS3DEV)/bin ] || mkdir -p $(PS3DEV)/bin + @install -m 755 $(OUTPUT) $(PS3DEV)/bin + +#--------------------------------------------------------------------------------- +run: + $(OUTPUT) + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + @echo linking ... $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + +#--------------------------------------------------------------------------------- +# Compile Targets for C/C++ +#--------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------- +%.o : %.cpp + @echo $(notdir $<) + @$(CXX) -E -MMD $(CFLAGS) $< > /dev/null + @$(CXX) $(OSXCXXFLAGS) $(CFLAGS) -o $@ -c $< + +#--------------------------------------------------------------------------------- +%.o : %.c + @echo $(notdir $<) + @$(CC) -E -MMD $(CFLAGS) $< > /dev/null + @$(CC) $(OSXCFLAGS) $(CFLAGS) -o $@ -c $< + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/client/source/main.c b/client/source/main.c new file mode 100644 index 0000000..78e8539 --- /dev/null +++ b/client/source/main.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2008 dhewg, #wiidev efnet + * + * this file is part of geckoloader + * http://wiibrew.org/index.php?title=Geckoloader + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#else +#include +#endif + +#include + +#ifndef __WIN32__ +static const char *desc_export = "export"; +#else +static const char *desc_export = "set"; +#endif + +#define PS3LOAD_VERSION_MAYOR 0 +#define PS3LOAD_VERSION_MINOR 5 + +#define LD_TCP_PORT 4299 + +#define MAX_ARGS_LEN 1024 + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; + +typedef enum { false, true } bool; + + +static const char *envvar = "PS3LOAD"; + +static bool tcp_write (int s, const void *buf, u32 len) { + s32 left, block; + const char *p; + + left = len; + p = buf; + while (left) { + block = send (s, p, left, 0); + + if (block < 0) { + perror ("send failed"); + return false; + } + + left -= block; + p += block; + } + + return true; +} + +static bool send_tcp (const char *host, const u8 *buf, u32 len, u32 len_un, + const char *args, u16 args_len) { + struct sockaddr_in sa; + struct hostent *he; + int s, bc; + u8 b[4]; + off_t left, block; + const u8 *p; + +#ifdef __WIN32__ + WSADATA wsa_data; + if (WSAStartup (MAKEWORD(2,2), &wsa_data)) { + printf ("WSAStartup failed\n"); + return false; + } +#endif + + memset (&sa, 0, sizeof (sa)); + + sa.sin_addr.s_addr = inet_addr (host); + + if (sa.sin_addr.s_addr == INADDR_NONE) { + printf ("resolving %s\n", host); + + he = gethostbyname (host); + + if (!he) { +#ifndef __WIN32__ + herror ("error resolving hostname"); +#else + fprintf (stderr, "error resolving hostname\n"); +#endif + return false; + } + + if (he->h_addrtype != AF_INET) { + fprintf (stderr, "unsupported address"); + return false; + } + + sa.sin_addr.s_addr = *((u32 *) he->h_addr); + } + + s = socket (PF_INET, SOCK_STREAM, 0); + + if (s < 0) { + perror ("error creating socket"); + return false; + } + + sa.sin_port = htons (LD_TCP_PORT); + sa.sin_family = AF_INET; + + printf ("connecting to %s:%d\n", inet_ntoa (sa.sin_addr), LD_TCP_PORT); + + if (connect (s, (struct sockaddr *) &sa, sizeof (sa)) == -1) { + perror ("error connecting"); + close (s); + return false; + } + + printf ("sending upload request\n"); + + b[0] = 'H'; + b[1] = 'A'; + b[2] = 'X'; + b[3] = 'X'; + + if (!tcp_write (s, b, 4)) { + close (s); + return false; + } + + b[0] = PS3LOAD_VERSION_MAYOR; + b[1] = PS3LOAD_VERSION_MINOR; + b[2] = (args_len >> 8) & 0xff; + b[3] = args_len & 0xff; + + if (!tcp_write (s, b, 4)) { + close (s); + return false; + } + + printf ("sending file size (%u bytes)\n", len); + + b[0] = (len >> 24) & 0xff; + b[1] = (len >> 16) & 0xff; + b[2] = (len >> 8) & 0xff; + b[3] = len & 0xff; + + if (!tcp_write (s, b, 4)) { + close (s); + return false; + } + + b[0] = (len_un >> 24) & 0xff; + b[1] = (len_un >> 16) & 0xff; + b[2] = (len_un >> 8) & 0xff; + b[3] = len_un & 0xff; + + if (!tcp_write (s, b, 4)) { + close (s); + return false; + } + + printf ("sending data"); + fflush (stdout); + + left = len; + p = buf; + bc = 0; + while (left) { + block = left; + if (block > 4 * 1024) + block = 4 * 1024; + left -= block; + + if (!tcp_write (s, p, block)) { + close (s); + return false; + } + + p += block; + bc++; + + if (!(bc % 16)) { + printf ("."); + fflush (stdout); + } + } + + printf ("\n"); + + if (args_len) { + printf ("sending arguments (%u bytes)\n", args_len); + + if (!tcp_write (s, (u8 *) args, args_len)) { + close (s); + return false; + } + } + +#ifndef __WIN32__ + close (s); +#else + shutdown (s, SD_SEND); + closesocket (s); + WSACleanup (); +#endif + + return true; +} + +static void usage (const char *argv0) { + fprintf (stderr, "set the environment variable %s to a valid " + "destination.\n\n" + "examples:\n" + "\ttcp mode:\n" + "\t\t%s %s=tcp:wii\n" + "\t\t%s %s=tcp:192.168.0.30\n\n" + "usage:\n" + "\t%s \n\n", + envvar, + desc_export, envvar, + desc_export, envvar, + argv0); + exit (EXIT_FAILURE); +} + +int main (int argc, char **argv) { + int fd; + struct stat st; + char *ev; + bool compress = true; + u8 *buf, *bufz; + off_t fsize; + uLongf bufzlen = 0; + u32 len, len_un; + + int i, c; + char args[MAX_ARGS_LEN]; + char *arg_pos; + u16 args_len, args_left; + + bool res; + + printf ("ps3load v%u.%u\n" + "coded by dhewg, #wiidev efnet\n\n", + PS3LOAD_VERSION_MAYOR, PS3LOAD_VERSION_MINOR); + + if (argc < 2) + usage (*argv); + + ev = getenv (envvar); + if (!ev) + usage (*argv); + + fd = open (argv[1], O_RDONLY | O_BINARY); + if (fd < 0) { + perror ("error opening the file"); + exit (EXIT_FAILURE); + } + + if (fstat (fd, &st)) { + close (fd); + perror ("error stat'ing the file"); + exit (EXIT_FAILURE); + } + + fsize = st.st_size; + + if (fsize < 512){ + close (fd); + fprintf (stderr, "error: invalid file size\n"); + exit (EXIT_FAILURE); + } + + buf = malloc (fsize); + if (!buf) { + close (fd); + fprintf (stderr, "out of memory\n"); + exit (EXIT_FAILURE); + } + + if (read (fd, buf, fsize) != fsize) { + close (fd); + free (buf); + perror ("error reading the file"); + exit (EXIT_FAILURE); + } + close (fd); + + len = fsize; + len_un = 0; + + if (!memcmp(buf, "PK\x03\x04", 4)) + compress = false; + + if (compress) { + bufzlen = (uLongf) ((float) fsize * 1.02); + + bufz = malloc (bufzlen); + if (!bufz) { + fprintf (stderr, "out of memory\n"); + exit (EXIT_FAILURE); + } + + printf("compressing %u bytes...", (u32) fsize); + fflush(stdout); + + res = compress2 (bufz, &bufzlen, buf, fsize, 6); + if (res != Z_OK) { + free(buf); + free(bufz); + fprintf (stderr, "error compressing data: %d\n", res); + exit (EXIT_FAILURE); + } + + if (bufzlen < (u32) fsize) { + printf(" %.2f%%\n", 100.0f * (float) bufzlen / (float) fsize); + + len = bufzlen; + len_un = fsize; + free(buf); + buf = bufz; + } else { + printf(" compressed size gained size, discarding\n"); + free(bufz); + } + } + + args_len = 0; + + arg_pos = args; + args_left = MAX_ARGS_LEN; + + c = snprintf (arg_pos, args_left, "%s", basename (argv[1])); + arg_pos += c + 1; + args_left -= c + 1; + + if (argc > 2) { + for (i = 2; i < argc; ++i) { + c = snprintf (arg_pos, args_left, "%s", argv[i]); + + if (c >= args_left) { + free (buf); + fprintf (stderr, "argument string too long\n"); + exit (EXIT_FAILURE); + } + + arg_pos += c + 1; + args_left -= c + 1; + } + + if (args_left < 1) { + free (buf); + fprintf (stderr, "argument string too long\n"); + exit (EXIT_FAILURE); + } + } + + arg_pos[0] = 0; + args_len = MAX_ARGS_LEN - args_left + 1; + + if (strncmp (ev, "tcp:", 4)) { + usage (*argv); + } else { + if (strlen (ev) < 5) + usage (*argv); + + res = send_tcp (&ev[4], buf, len, len_un, args, args_len); + } + + if (res) + printf ("done.\n"); + else + printf ("transfer failed.\n"); + + free (buf); + + return 0; +} +