rockbox/firmware/target/hosted/filesystem-unix.c
Christian Soffke 1745b74576 Make simulator compile on MacOS
Tested on MacOS Sequoia (Apple Silicon) with the
latest Xcode command line tools, gcc 14
(Homebrew GCC 14.2.0_1) and sdl2 (Homebrew 2.30.9)

Make sure 'gcc' (and 'gcc-ar') is in your PATH
ahead of the Xcode-provided "gcc"(clang). E.g.
by setting up symlinks in /usr/local/bin that
point to gcc-14 and gcc-ar-14.

Notes:
- The appropriate bmp from uisimulator/bitmaps
  has to be manually copied to your build folder
  and renamed to UI256.bmp, if you want the sim
  background to be displayed

Change-Id: I559f33d2165065f913f30c016b85906af380fb81
2024-11-30 22:19:02 -05:00

250 lines
5.8 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 by Thomas Martitz
*
* 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#define RB_FILESYSTEM_OS
#ifdef __APPLE__
#include <sys/param.h>
#include <sys/mount.h>
#else
#include <sys/statfs.h> /* lowest common denominator */
#endif
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <utime.h>
#include "config.h"
#include "system.h"
#include "file.h"
#include "dir.h"
#include "mv.h"
#include "debug.h"
#include "pathfuncs.h"
#include "string-extra.h"
int os_volume_path(IF_MV(int volume, ) char *buffer, size_t bufsize);
#define SAME_FILE_INFO(sb1p, sb2p) \
((sb1p)->st_dev == (sb2p)->st_dev && (sb1p)->st_ino == (sb2p)->st_ino)
int os_modtime(const char *path, time_t modtime)
{
struct utimbuf times =
{
.actime = modtime,
.modtime = modtime,
};
return utime(path, &times);
}
off_t os_filesize(int osfd)
{
struct stat sb;
if (!os_fstat(osfd, &sb))
return sb.st_size;
else
return -1;
}
int os_fsamefile(int osfd1, int osfd2)
{
struct stat sb1, sb2;
if (os_fstat(osfd1, &sb1))
return -1;
if (os_fstat(osfd2, &sb2))
return -1;
return SAME_FILE_INFO(&sb1, &sb2);
}
int os_relate(const char *ospath1, const char *ospath2)
{
DEBUGF("\"%s\" : \"%s\"\n", ospath1, ospath2);
if (!ospath2 || !*ospath2)
{
errno = ospath2 ? ENOENT : EFAULT;
return -1;
}
/* First file must stay open for duration so that its stats don't change */
int fd1 = os_open(ospath1, O_RDONLY | O_CLOEXEC);
if (fd1 < 0)
return -2;
struct stat sb1;
if (os_fstat(fd1, &sb1))
{
os_close(fd1);
return -3;
}
char path2buf[strlen(ospath2) + 1];
*path2buf = 0;
ssize_t len = 0;
const char *p = ospath2;
const char *sepmo = path_is_absolute(ospath2) ? PA_SEP_HARD : PA_SEP_SOFT;
int rc = RELATE_DIFFERENT;
while (1)
{
if (sepmo != PA_SEP_HARD &&
!(len = parse_path_component(&ospath2, &p)))
{
break;
}
char compname[len + 1];
strmemcpy(compname, p, len);
path_append(path2buf, sepmo, compname, sizeof (path2buf));
sepmo = PA_SEP_SOFT;
int errnum = errno; /* save and restore if not actually failing */
struct stat sb2;
if (!os_stat(path2buf, &sb2))
{
if (SAME_FILE_INFO(&sb1, &sb2))
{
rc = RELATE_SAME;
}
else if (rc == RELATE_SAME)
{
if (name_is_dot_dot(compname))
rc = RELATE_DIFFERENT;
else if (!name_is_dot(compname))
rc = RELATE_PREFIX;
}
}
else if (errno == ENOENT && !*GOBBLE_PATH_SEPCH(ospath2) &&
!name_is_dot_dot(compname))
{
if (rc == RELATE_SAME)
rc = RELATE_PREFIX;
errno = errnum;
break;
}
else
{
rc = -4;
break;
}
}
if (os_close(fd1) && rc >= 0)
rc = -5;
return rc;
}
bool os_file_exists(const char *ospath)
{
int sim_fd = os_open(ospath, O_RDONLY | O_CLOEXEC, 0);
if (sim_fd < 0)
return false;
int errnum = errno;
os_close(sim_fd);
errno = errnum;
return true;
}
int os_opendirfd(const char *osdirname)
{
return os_open(osdirname, O_RDONLY | O_CLOEXEC);
}
int os_opendir_and_fd(const char *osdirname, DIR **osdirpp, int *osfdp)
{
/* another possible way is to use open() then fdopendir() */
*osdirpp = NULL;
*osfdp = -1;
DIR *dirp = os_opendir(osdirname);
if (!dirp)
return -1;
int rc = 0;
int errnum = errno;
int fd = os_dirfd(dirp);
if (fd < 0)
{
fd = os_opendirfd(osdirname);
rc = 1;
}
if (fd < 0)
{
os_closedir(dirp);
return -2;
}
errno = errnum;
*osdirpp = dirp;
*osfdp = fd;
return rc;
}
/* do we really need this in the app? (in the sim, yes) */
void volume_size(IF_MV(int volume,) sector_t *sizep, sector_t *freep)
{
sector_t size = 0, free = 0;
char volpath[MAX_PATH];
struct statfs fs;
if (os_volume_path(IF_MV(volume,) volpath, sizeof (volpath)) >= 0
&& !statfs(volpath, &fs))
{
#ifdef __APPLE__
DEBUGF("statvfs: frsize=%d blocks=%ld bfree=%ld\n",
(int)fs.f_bsize, (long)fs.f_blocks, (long)fs.f_bfree);
if (sizep)
size = (fs.f_blocks / 2) * (fs.f_bsize / 512);
if (freep)
free = (fs.f_bfree / 2) * (fs.f_bsize / 512);
#else
DEBUGF("statvfs: frsize=%d blocks=%ld bfree=%ld\n",
(int)fs.f_frsize, (long)fs.f_blocks, (long)fs.f_bfree);
if (sizep)
size = (fs.f_blocks / 2) * (fs.f_frsize / 512);
if (freep)
free = (fs.f_bfree / 2) * (fs.f_frsize / 512);
#endif
}
if (sizep)
*sizep = size;
if (freep)
*freep = free;
}