/*************************************************************************** * __________ __ ___. * 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 #include /* lowest common denominator */ #include #include #include #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" #define SAME_FILE_INFO(sb1p, sb2p) \ ((sb1p)->st_dev == (sb2p)->st_dev && (sb1p)->st_ino == (sb2p)->st_ino) 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); 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, 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); } 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,) unsigned long *sizep, unsigned long *freep) { unsigned long 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)) { 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); } if (sizep) *sizep = size; if (freep) *freep = free; }