コード例 #1
0
int retro_vfs_file_rename_impl(const char *old_path, const char *new_path)
{
   char *old_path_local    = NULL;
   char *new_path_local    = NULL;
   wchar_t *old_path_wide  = NULL;
   wchar_t *new_path_wide  = NULL;

   if (!old_path || !*old_path || !new_path || !*new_path)
      return -1;

   (void)old_path_local;
   (void)new_path_local;
   (void)old_path_wide;
   (void)new_path_wide;

#if defined(_WIN32) && !defined(_XBOX)
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
   old_path_local = utf8_to_local_string_alloc(old_path);
   new_path_local = utf8_to_local_string_alloc(new_path);

   if (old_path_local)
   {
      if (new_path_local)
      {
         int ret = rename(old_path_local, new_path_local);
         free(old_path_local);
         free(new_path_local);
         return ret==0 ? 0 : -1;
      }

      free(old_path_local);
   }

   if (new_path_local)
      free(new_path_local);
#else
   old_path_wide = utf8_to_utf16_string_alloc(old_path);
   new_path_wide = utf8_to_utf16_string_alloc(new_path);

   if (old_path_wide)
   {
      if (new_path_wide)
      {
         int ret = _wrename(old_path_wide, new_path_wide);
         free(old_path_wide);
         free(new_path_wide);
         return ret==0 ? 0 : -1;
      }

      free(old_path_wide);
   }

   if (new_path_wide)
      free(new_path_wide);
#endif
   return -1;
#else
   return rename(old_path, new_path)==0 ? 0 : -1;
#endif
}
コード例 #2
0
ファイル: nbio_stdio.c プロジェクト: Monroe88/RetroArch
static void *nbio_stdio_open(const char * filename, unsigned mode)
{
   void *buf                   = NULL;
   struct nbio_stdio_t* handle = NULL;
   size_t len                  = 0;
#if !defined(_WIN32) || defined(LEGACY_WIN32)
   FILE* f                     = fopen(filename, stdio_modes[mode]);
#else
   wchar_t *filename_wide      = utf8_to_utf16_string_alloc(filename);
   FILE* f                     = _wfopen(filename_wide, stdio_modes[mode]);

   if (filename_wide)
      free(filename_wide);
#endif
   if (!f)
      return NULL;

   handle                = (struct nbio_stdio_t*)malloc(sizeof(struct nbio_stdio_t));

   if (!handle)
      goto error;

   handle->f             = f;

   switch (mode)
   {
      case NBIO_WRITE:
      case BIO_WRITE:
         break;
      default:
         fseek(handle->f, 0, SEEK_END);
         len = ftell(handle->f);
         break;
   }

   handle->mode          = mode;

   if (len)
      buf                = malloc(len);

   if (len && !buf)
      goto error;

   handle->data          = buf;
   handle->len           = len;
   handle->progress      = handle->len;
   handle->op            = -2;

   return handle;

error:
   if (handle)
      free(handle);
   fclose(f);
   return NULL;
}
コード例 #3
0
ファイル: nbio_windowsmmap.c プロジェクト: RobLoach/RetroArch
static void *nbio_mmap_win32_open(const char * filename, unsigned mode)
{
   static const DWORD dispositions[] = { OPEN_EXISTING, CREATE_ALWAYS, OPEN_ALWAYS, OPEN_EXISTING, CREATE_ALWAYS };
   HANDLE mem;
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500
   LARGE_INTEGER len;
#else
   SIZE_T len;
#endif
   struct nbio_mmap_win32_t* handle  = NULL;
   void* ptr                         = NULL;
   bool is_write                     = (mode == NBIO_WRITE || mode == NBIO_UPDATE || mode == BIO_WRITE);
   DWORD access                      = (is_write ? GENERIC_READ|GENERIC_WRITE : GENERIC_READ);
#if !defined(_WIN32) || defined(LEGACY_WIN32)
   HANDLE file                       = CreateFile(filename, access, FILE_SHARE_ALL, NULL, dispositions[mode], FILE_ATTRIBUTE_NORMAL, NULL);
#else
   wchar_t *filename_wide            = utf8_to_utf16_string_alloc(filename);
   HANDLE file                       = CreateFileW(filename_wide, access, FILE_SHARE_ALL, NULL, dispositions[mode], FILE_ATTRIBUTE_NORMAL, NULL);

   if (filename_wide)
      free(filename_wide);
#endif

   if (file == INVALID_HANDLE_VALUE)
      return NULL;

#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500
   /* GetFileSizeEx is new for Windows 2000 */
   GetFileSizeEx(file, &len);
   mem = CreateFileMapping(file, NULL, is_write ? PAGE_READWRITE : PAGE_READONLY, 0, 0, NULL);
   ptr = MapViewOfFile(mem, is_write ? (FILE_MAP_READ|FILE_MAP_WRITE) : FILE_MAP_READ, 0, 0, len.QuadPart);
#else
   GetFileSize(file, &len);
   mem = CreateFileMapping(file, NULL, is_write ? PAGE_READWRITE : PAGE_READONLY, 0, 0, NULL);
   ptr = MapViewOfFile(mem, is_write ? (FILE_MAP_READ|FILE_MAP_WRITE) : FILE_MAP_READ, 0, 0, len);
#endif

   CloseHandle(mem);

   handle           = (struct nbio_mmap_win32_t*)malloc(sizeof(struct nbio_mmap_win32_t));

   handle->file     = file;
   handle->is_write = is_write;
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500
   handle->len      = len.QuadPart;
#else
   handle->len      = len;
#endif
   handle->ptr      = ptr;

   return handle;
}
コード例 #4
0
int retro_vfs_file_remove_impl(const char *path)
{
   char *path_local    = NULL;
   wchar_t *path_wide  = NULL;

   if (!path || !*path)
      return -1;

   (void)path_local;
   (void)path_wide;

#if defined(_WIN32) && !defined(_XBOX)
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
   path_local = utf8_to_local_string_alloc(path);

   if (path_local)
   {
      int ret = remove(path_local);
      free(path_local);

      if (ret == 0)
         return 0;
   }
#else
   path_wide = utf8_to_utf16_string_alloc(path);

   if (path_wide)
   {
      int ret = _wremove(path_wide);
      free(path_wide);

      if (ret == 0)
         return 0;
   }
#endif
#else
   if (remove(path) == 0)
      return 0;
#endif
   return -1;
}
コード例 #5
0
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints)
{
   int                                flags = 0;
   const char                     *mode_str = NULL;
   libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream));

#ifdef VFS_FRONTEND
   const char                 *dumb_prefix  = "vfsonly://";
   int                      dumb_prefix_len = (int)strlen(dumb_prefix);
   int                             path_len = (int)strlen(path);

   if (path_len >= dumb_prefix_len)
      if (!memcmp(path, dumb_prefix, dumb_prefix_len))
         path += strlen(dumb_prefix);
#endif

   if (!stream)
      return NULL;

   (void)flags;

   stream->hints           = hints;
   stream->orig_path       = strdup(path);

#ifdef HAVE_MMAP
   if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS && mode == RETRO_VFS_FILE_ACCESS_READ)
      stream->hints |= RFILE_HINT_UNBUFFERED;
   else
#endif
      stream->hints &= ~RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS;

   switch (mode)
   {
      case RETRO_VFS_FILE_ACCESS_READ:
         mode_str = "rb";

         flags    = O_RDONLY;
#ifdef _WIN32
         flags   |= O_BINARY;
#endif
         break;

      case RETRO_VFS_FILE_ACCESS_WRITE:
         mode_str = "wb";

         flags    = O_WRONLY | O_CREAT | O_TRUNC;
#if defined(PS2)
         flags   |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
         flags   |= S_IRUSR | S_IWUSR;
#else
         flags   |= O_BINARY;
#endif
         break;

      case RETRO_VFS_FILE_ACCESS_READ_WRITE:
         mode_str = "w+b";

         flags    = O_RDWR | O_CREAT | O_TRUNC;
#if defined(PS2)
         flags   |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
         flags   |= S_IRUSR | S_IWUSR;
#else
         flags   |= O_BINARY;
#endif
         break;

      case RETRO_VFS_FILE_ACCESS_WRITE | RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING:
      case RETRO_VFS_FILE_ACCESS_READ_WRITE | RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING:
         mode_str = "r+b";

         flags    = O_RDWR;
#if defined(PS2)
         flags   |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
         flags   |= S_IRUSR | S_IWUSR;
#else
         flags   |= O_BINARY;
#endif
         break;
         
      default:
         goto error;
   }

   if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
   {
      FILE   *fp = (FILE*)fopen_utf8(path, mode_str);

      if (!fp)
         goto error;

      /* Regarding setvbuf:
       *
       * https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
       *
       * If the size argument is not zero but buf is NULL, a buffer of the given size will be allocated immediately, and
       * released on close. This is an extension to ANSI C.
       *
       * Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it.
       */
      /* TODO: this is only useful for a few platforms, find which and add ifdef */
      stream->fp  = fp;
      stream->buf = (char*)calloc(1, 0x4000);
      setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
   }
   else
   {
#if defined(_WIN32) && !defined(_XBOX)
#if defined(LEGACY_WIN32)
      char *path_local    = utf8_to_local_string_alloc(path);
      stream->fd          = open(path_local, flags, 0);
      if (path_local)
         free(path_local);
#else
      wchar_t * path_wide = utf8_to_utf16_string_alloc(path);
      stream->fd          = _wopen(path_wide, flags, 0);
      if (path_wide)
         free(path_wide);
#endif
#else
      stream->fd = open(path, flags, 0);
#endif

      if (stream->fd == -1)
         goto error;

#ifdef HAVE_MMAP
      if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
      {
         stream->mappos  = 0;
         stream->mapped  = NULL;
         stream->mapsize = retro_vfs_file_seek_internal(stream, 0, SEEK_END);

         if (stream->mapsize == (uint64_t)-1)
            goto error;

         retro_vfs_file_seek_internal(stream, 0, SEEK_SET);

         stream->mapped = (uint8_t*)mmap((void*)0,
               stream->mapsize, PROT_READ,  MAP_SHARED, stream->fd, 0);

         if (stream->mapped == MAP_FAILED)
            stream->hints &= ~RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS;
      }
#endif
   }

   retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
   retro_vfs_file_seek_internal(stream, 0, SEEK_END);

   stream->size = retro_vfs_file_tell_impl(stream);

   retro_vfs_file_seek_internal(stream, 0, SEEK_SET);

   return stream;

error:
   retro_vfs_file_close_impl(stream);
   return NULL;
}
コード例 #6
0
ファイル: file_path.c プロジェクト: gouchi/RetroArch
/**
 * path_mkdir:
 * @dir                : directory
 *
 * Create directory on filesystem.
 *
 * Returns: true (1) if directory could be created, otherwise false (0).
 **/
bool path_mkdir(const char *dir)
{
   /* Use heap. Real chance of stack overflow if we recurse too hard. */
   const char *target = NULL;
   bool         sret  = false;
   bool norecurse     = false;
   char     *basedir  = NULL;

   if (dir && *dir)
      basedir         = strdup(dir);

   if (!basedir)
      return false;

   path_parent_dir(basedir);
   if (!*basedir || !strcmp(basedir, dir))
      goto end;

   if (path_is_directory(basedir))
   {
      target    = dir;
      norecurse = true;
   }
   else
   {
      target    = basedir;
      sret      = path_mkdir(basedir);

      if (sret)
      {
         target    = dir;
         norecurse = true;
      }
   }

   if (norecurse)
   {
#if defined(_WIN32)
#ifdef LEGACY_WIN32
      int ret = _mkdir(dir);
#else
      wchar_t *dirW = utf8_to_utf16_string_alloc(dir);
      int ret = -1;

      if (dirW)
      {
         ret = _wmkdir(dirW);
         free(dirW);
      }
#endif
#elif defined(IOS)
      int ret = mkdir(dir, 0755);
#elif defined(VITA) || defined(PSP)
      int ret = sceIoMkdir(dir, 0777);
#elif defined(__QNX__)
      int ret = mkdir(dir, 0777);
#else
      int ret = mkdir(dir, 0750);
#endif

      /* Don't treat this as an error. */
      if (path_mkdir_error(ret) && path_is_directory(dir))
         ret = 0;

      if (ret < 0)
         printf("mkdir(%s) error: %s.\n", dir, strerror(errno));
      sret = (ret == 0);
   }

end:
   if (target && !sret)
      printf("Failed to create directory: \"%s\".\n", target);
   free(basedir);
   return sret;
}
コード例 #7
0
ファイル: file_path.c プロジェクト: gouchi/RetroArch
static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
{
#if defined(VITA) || defined(PSP)
   SceIoStat buf;
   char *tmp  = strdup(path);
   size_t len = strlen(tmp);
   if (tmp[len-1] == '/')
      tmp[len-1]='\0';

   if (sceIoGetstat(tmp, &buf) < 0)
   {
      free(tmp);
      return false;
   }
   free(tmp);

#elif defined(__CELLOS_LV2__)
    CellFsStat buf;
    if (cellFsStat(path, &buf) < 0)
       return false;
#elif defined(_WIN32)
   struct _stat buf;
   char *path_local;
   wchar_t *path_wide;
   DWORD file_info;

   if (!path || !*path)
      return false;

   (void)path_wide;
   (void)path_local;
   (void)file_info;

#if defined(LEGACY_WIN32)
   path_local = utf8_to_local_string_alloc(path);
   file_info  = GetFileAttributes(path_local);

   _stat(path_local, &buf);

   if (path_local)
     free(path_local);
#else
   path_wide = utf8_to_utf16_string_alloc(path);
   file_info = GetFileAttributesW(path_wide);

   _wstat(path_wide, &buf);

   if (path_wide)
      free(path_wide);
#endif

   if (file_info == INVALID_FILE_ATTRIBUTES)
      return false;
#else
   struct stat buf;
   if (stat(path, &buf) < 0)
      return false;
#endif

   if (size)
      *size = (int32_t)buf.st_size;

   switch (mode)
   {
      case IS_DIRECTORY:
#if defined(VITA) || defined(PSP)
         return FIO_S_ISDIR(buf.st_mode);
#elif defined(__CELLOS_LV2__)
         return ((buf.st_mode & S_IFMT) == S_IFDIR);
#elif defined(_WIN32)
         return (file_info & FILE_ATTRIBUTE_DIRECTORY);
#else
         return S_ISDIR(buf.st_mode);
#endif
      case IS_CHARACTER_SPECIAL:
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(_WIN32)
         return false;
#else
         return S_ISCHR(buf.st_mode);
#endif
      case IS_VALID:
         return true;
   }

   return false;
}