<commit_before>/**
 * @file posix/fs.cpp
 * @brief POSIX filesystem/directory access/notification
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * MacOS X fsevents code based on osxbook.com/software/fslogger
 * (requires euid == root or passing an existing /dev/fsevents fd)
 * (c) <NAME>
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega.h"
#include <sys/utsname.h>
#include <sys/ioctl.h>

namespace mega {
PosixFileAccess::PosixFileAccess(int defaultfilepermissions)
{
    fd = -1;
    this->defaultfilepermissions = defaultfilepermissions;

#ifndef HAVE_FDOPENDIR
    dp = NULL;
#endif

    fsidvalid = false;
}

PosixFileAccess::~PosixFileAccess()
{
#ifndef HAVE_FDOPENDIR
    if (dp)
    {
        closedir(dp);
    }
#endif

    if (fd >= 0)
    {
        close(fd);
    }
}

bool PosixFileAccess::sysstat(m_time_t* mtime, m_off_t* size)
{
    struct stat statbuf;
    retry = false;

    if (!stat(localname.c_str(), &statbuf))
    {
        if (S_ISDIR(statbuf.st_mode))
        {
            return false;
        }

        *size = statbuf.st_size;
        *mtime = statbuf.st_mtime;

        FileSystemAccess::captimestamp(mtime);

        return true;
    }

    return false;
}

bool PosixFileAccess::sysopen()
{
    return (fd = open(localname.c_str(), O_RDONLY)) >= 0;
}

void PosixFileAccess::sysclose()
{
    if (localname.size())
    {
        // fd will always be valid at this point
        close(fd);
        fd = -1;
    }
}

// update local name
void PosixFileAccess::updatelocalname(string* name)
{
    if (localname.size())
    {
        localname = *name;
    }
}

bool PosixFileAccess::sysread(byte* dst, unsigned len, m_off_t pos)
{
#ifndef __ANDROID__
    return pread(fd, (char*)dst, len, pos) == len;
#else
    lseek(fd, pos, SEEK_SET);
    return read(fd, (char*)dst, len) == len;
#endif
}

bool PosixFileAccess::fwrite(const byte* data, unsigned len, m_off_t pos)
{
#ifndef __ANDROID__
    return pwrite(fd, data, len, pos) == len;
#else
    lseek(fd, pos, SEEK_SET);
    return write(fd, data, len) == len;
#endif
}

bool PosixFileAccess::fopen(string* f, bool read, bool write)
{
    struct stat statbuf;

    retry = false;
<commit_msg>Checks and avoid fopen for invalid case names (OS X)<commit_after>/**
 * @file posix/fs.cpp
 * @brief POSIX filesystem/directory access/notification
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * MacOS X fsevents code based on osxbook.com/software/fslogger
 * (requires euid == root or passing an existing /dev/fsevents fd)
 * (c) <NAME>
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega.h"
#include <sys/utsname.h>
#include <sys/ioctl.h>

namespace mega {
PosixFileAccess::PosixFileAccess(int defaultfilepermissions)
{
    fd = -1;
    this->defaultfilepermissions = defaultfilepermissions;

#ifndef HAVE_FDOPENDIR
    dp = NULL;
#endif

    fsidvalid = false;
}

PosixFileAccess::~PosixFileAccess()
{
#ifndef HAVE_FDOPENDIR
    if (dp)
    {
        closedir(dp);
    }
#endif

    if (fd >= 0)
    {
        close(fd);
    }
}

bool PosixFileAccess::sysstat(m_time_t* mtime, m_off_t* size)
{
    struct stat statbuf;
    retry = false;

    if (!stat(localname.c_str(), &statbuf))
    {
        if (S_ISDIR(statbuf.st_mode))
        {
            return false;
        }

        *size = statbuf.st_size;
        *mtime = statbuf.st_mtime;

        FileSystemAccess::captimestamp(mtime);

        return true;
    }

    return false;
}

bool PosixFileAccess::sysopen()
{
    return (fd = open(localname.c_str(), O_RDONLY)) >= 0;
}

void PosixFileAccess::sysclose()
{
    if (localname.size())
    {
        // fd will always be valid at this point
        close(fd);
        fd = -1;
    }
}

// update local name
void PosixFileAccess::updatelocalname(string* name)
{
    if (localname.size())
    {
        localname = *name;
    }
}

bool PosixFileAccess::sysread(byte* dst, unsigned len, m_off_t pos)
{
#ifndef __ANDROID__
    return pread(fd, (char*)dst, len, pos) == len;
#else
    lseek(fd, pos, SEEK_SET);
    return read(fd, (char*)dst, len) == len;
#endif
}

bool PosixFileAccess::fwrite(const byte* data, unsigned len, m_off_t pos)
{
#ifndef __ANDROID__
    return pwrite(fd, data, len, pos) == len;
#else
    lseek(fd, pos, SEEK_SET);
    return write(fd, data, len) == len;
#endif
}

bool PosixFileAccess::fopen(string* f, bool read, bool write)
{
    struct stat statbuf;

    retry = false;

#ifdef __MACH__
    if (read)
    {
        char resolved_path[PATH_MAX];
        struct stat statbuf;
        if (memcmp(f->c_str(), ".", 2) && memcmp(f->c_str(), "..", 3)
                && !lstat(f->c_str(), &statbuf)
                && !S_ISLNK(statbuf.st_mode)
                && realpath(f->c_str(), resolved_path) == resolved_path)
        {
            const char *fname;
            size_t fnamesize;
            if ((fname = strrchr(f->c_str(), '/')))
            {
                fname++;
                fnamesize = f->size() - (fname - f->c_str());
            }
            else
            {
                fname =  f->c_str();
                fnamesize = f->size();
            }
            fnamesize++;

            const char *rname;
            size_t rnamesize;
            if ((rname = strrchr(resolved_path, '/')))
            {
                rname++;
            }
            else
            {
                rname = resolved_path;
            }
            rnamesize = strlen(rname) + 1;

            if (rnamesize == fnamesize && memcmp(fname, rname, fnamesize))
            {
                LOG_warn << "fopen failed due to invalid case: " << f->c_str();
                return false;
            }
        }
    }
#endif

{'fraction_non_alphanumeric': 0.119514752134192, 'fraction_numerical': 0.004343267934701213, 'mean_word_length': 2.4298921417565484, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5239793', 'n_tokens_mistral': 2290, 'n_tokens_neox': 2214, 'n_words': 618}