void QLinuxFbScreenPrivate::openTty()
{
    const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};

    if (ttyDevice.isEmpty()) {
        for (const char * const *dev = devs; *dev; ++dev) {
            ttyfd = QT_OPEN(*dev, O_RDWR);
            if (ttyfd != -1)
                break;
        }
    } else {
        ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR);
    }

    if (ttyfd == -1)
        return;

    if (doGraphicsMode) {
        ioctl(ttyfd, KDGETMODE, &oldKdMode);
        if (oldKdMode != KD_GRAPHICS) {
            int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
            if (ret == -1)
                doGraphicsMode = false;
        }
    }

    // No blankin' screen, no blinkin' cursor!, no cursor!
    const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
    QT_WRITE(ttyfd, termctl, sizeof(termctl));
}
Exemplo n.º 2
0
QT_BEGIN_NAMESPACE

/*!
    \class QWSQnxKeyboardHandler
    \preliminary
    \ingroup qws
    \since 4.6
    \internal

    \brief The QWSQnxKeyboardHandler class implements a keyboard driver
    for the QNX \c{devi-hid} input manager.

    To be able to compile this mouse handler, \l{Qt for Embedded Linux}
    must be configured with the \c -qt-kbd-qnx option, see the
    \l{Qt for Embedded Linux Character Input} documentation for details.

    In order to use this keyboard handler, the \c{devi-hid} input manager
    must be set up and run with the resource manager interface (option \c{-r}).
    Also, Photon must not be running.

    Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
    Note that after running \c{devi-hid}, you will not be able to use the local
    shell anymore. It is suggested to run the command in a shell scrip, that launches
    a Qt application after invocation of \c{devi-hid}.

    To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard
    handler, set the QWS_KEYBOARD environment variable to \c{qnx}. By default,
    the first keyboard device (\c{/dev/devi/keyboard0}) is used. To override, pass a device
    name as the first and only parameter, for example
    \c{QWS_KEYBOARD=qnx:/dev/devi/keyboard1; export QWS_KEYBOARD}.

    \sa {Qt for Embedded Linux Character Input}, {Qt for Embedded Linux}
*/

/*!
    Constructs a keyboard handler for the specified \a device, defaulting to
    \c{/dev/devi/keyboard0}.

    Note that you should never instanciate this class, instead let QKbdDriverFactory
    handle the keyboard handlers.

    \sa QKbdDriverFactory
 */
QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device)
{
    // open the keyboard device
    keyboardFD = QT_OPEN(device.isEmpty() ? "/dev/devi/keyboard0" : device.toLatin1().constData(),
                         QT_OPEN_RDONLY);
    if (keyboardFD == -1) {
        qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device");
        return;
    }

    // create a socket notifier so we'll wake up whenever keyboard input is detected.
    QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this);
    connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated()));

    qDebug() << "QWSQnxKeyboardHandler: connected.";

}
Exemplo n.º 3
0
QEvdevTabletHandler::QEvdevTabletHandler(const QString &spec, QObject *parent)
    : QObject(parent), d(0)
{
    setObjectName(QLatin1String("Evdev Tablet Handler"));
    d = new QEvdevTabletData(this);
    QString dev;
    QStringList args = spec.split(QLatin1Char(':'));
    for (int i = 0; i < args.count(); ++i) {
        if (args.at(i).startsWith(QLatin1String("/dev/"))) {
            dev = args.at(i);
            break;
        }
    }
    if (dev.isEmpty()) {
        QScopedPointer<QDeviceDiscovery> deviceDiscovery(
            QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this));
        if (deviceDiscovery) {
            QStringList devices = deviceDiscovery->scanConnectedDevices();
            if (!devices.isEmpty())
                dev = devices.at(0);
        }
    }
    if (!dev.isEmpty()) {
        qDebug("evdevtablet: using %s", qPrintable(dev));
        d->fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
        if (d->fd >= 0) {
            d->testGrab();
            if (d->queryLimits()) {
                d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this);
                connect(d->notifier, SIGNAL(activated(int)), this, SLOT(readData()));
            }
Exemplo n.º 4
0
QLinuxInputMouseHandler::QLinuxInputMouseHandler(const QString &key,
                                                 const QString &specification)
    : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), m_xoffset(0), m_yoffset(0), m_buttons(0), d(0)
{
    qDebug() << "QLinuxInputMouseHandler" << key << specification;


    setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler"));

    QString dev = QLatin1String("/dev/input/event0");
    m_compression = true;
    m_smooth = false;
    int jitterLimit = 0;
    
    QStringList args = specification.split(QLatin1Char(':'));
    foreach (const QString &arg, args) {
        if (arg == "nocompress")
            m_compression = false;
        else if (arg.startsWith("dejitter="))
            jitterLimit = arg.mid(9).toInt();
        else if (arg.startsWith("xoffset="))
            m_xoffset = arg.mid(8).toInt();
        else if (arg.startsWith("yoffset="))
            m_yoffset = arg.mid(8).toInt();
        else if (arg.startsWith(QLatin1String("/dev/")))
            dev = arg;
    }
    m_jitterLimitSquared = jitterLimit*jitterLimit; 
    
    m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
    if (m_fd >= 0) {
        m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
        connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
    } else {
QT_BEGIN_NAMESPACE

QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device)
    : QObject(), QWSMouseHandler(driver, device)
{
    QString mouseDev = device;
    if (device.isEmpty())
        mouseDev = QLatin1String("/dev/vmouse");

    mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY);
    if (mouseFD == -1) {
        perror("QVFbMouseHandler::QVFbMouseHandler");
        qWarning("QVFbMouseHander: Unable to open device %s",
                 qPrintable(mouseDev));
        return;
    }

    // Clear pending input
    char buf[2];
    while (QT_READ(mouseFD, buf, 1) > 0) { }

    mouseIdx = 0;

    mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
    connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
}
Exemplo n.º 6
0
QT_BEGIN_NAMESPACE

static int openFramebufferDevice(const QString &dev)
{
    int fd = -1;

    if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
        fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);

    if (fd == -1) {
        if (access(dev.toLatin1().constData(), R_OK) == 0)
            fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
    }

    return fd;
}
Exemplo n.º 7
0
QT_BEGIN_NAMESPACE

/*!
    \class QQnxMouseHandler
    \preliminary
    \ingroup qws
    \internal
    \since 4.6

    \brief The QQnxMouseHandler class implements a mouse driver
    for the QNX \c{devi-hid} input manager.

    To be able to compile this mouse handler, \l{Qt for Embedded Linux}
    must be configured with the \c -qt-mouse-qnx option, see the
    \l{Qt for Embedded Linux Pointer Handling}{Pointer Handling} documentation for details.

    In order to use this mouse handler, the \c{devi-hid} input manager
    must be set up and run with the resource manager interface (option \c{-r}).
    Also, Photon must not be running.

    Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
    Note that after running \c{devi-hid}, you will not be able to use the local
    shell anymore. It is suggested to run the command in a shell scrip, that launches
    a Qt application after invocation of \c{devi-hid}.

    To make \l{Qt for Embedded Linux} explicitly choose the qnx mouse
    handler, set the QWS_MOUSE_PROTO environment variable to \c{qnx}. By default,
    the first mouse device (\c{/dev/devi/mouse0}) is used. To override, pass a device
    name as the first and only parameter, for example
    \c{QWS_MOUSE_PROTO=qnx:/dev/devi/mouse1; export QWS_MOUSE_PROTO}.

    \sa {Qt for Embedded Linux Pointer Handling}{Pointer Handling}, {Qt for Embedded Linux}
*/

/*!
    Constructs a mouse handler for the specified \a device, defaulting to \c{/dev/devi/mouse0}.
    The \a driver parameter must be \c{"qnx"}.

    Note that you should never instanciate this class, instead let QMouseDriverFactory
    handle the mouse handlers.

    \sa QMouseDriverFactory
 */
QQnxMouseHandler::QQnxMouseHandler(const QString & /*driver*/, const QString &device)
{
    // open the mouse device with O_NONBLOCK so reading won't block when there's no data
    mouseFD = QT_OPEN(device.isEmpty() ? "/dev/devi/mouse0" : device.toLatin1().constData(),
                          QT_OPEN_RDONLY | O_NONBLOCK);
    if (mouseFD == -1) {
        qErrnoWarning(errno, "QQnxMouseHandler: Unable to open mouse device");
        return;
    }

    // register a socket notifier on the file descriptor so we'll wake up whenever
    // there's a mouse move waiting for us.
    mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
    connect(mouseNotifier, SIGNAL(activated(int)), SLOT(socketActivated()));

    qDebug() << "QQnxMouseHandler: connected.";
}
Exemplo n.º 8
0
QLock::QLock(const QString &filename, char id, bool create)
{
    data = new QLockData;
    data->count = 0;
#ifdef Q_NO_SEMAPHORE
    data->file = QString(filename+id).toLocal8Bit().constData();
    for(int x = 0; x < 2; x++) {
        data->id = QT_OPEN(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
        if(data->id != -1 || !create) {
            data->owned = x;
            break;
        }
    }
#else
    key_t semkey = ftok(filename.toLocal8Bit().constData(), id);
    data->id = semget(semkey,0,0);
    data->owned = create;
    if (create) {
        qt_semun arg; arg.val = 0;
        if (data->id != -1)
            semctl(data->id,0,IPC_RMID,arg);
        data->id = semget(semkey,1,IPC_CREAT|0600);
        arg.val = MAX_LOCKS;
        semctl(data->id,0,SETVAL,arg);

        QWSSignalHandler::instance()->addSemaphore(data->id);
    }
#endif
    if (data->id == -1) {
        int eno = errno;
        qWarning("Cannot %s semaphore %s '%c'", (create ? "create" : "get"),
                 qPrintable(filename), id);
        qDebug() << "Error" << eno << strerror(eno);
    }
}
Exemplo n.º 9
0
/*!
    Creates a lock. \a filename is the file path of the Unix-domain
    socket the \l{Qt for Embedded Linux} client is using. \a id is the name of the
    particular lock to be created on that socket. If \a create is true
    the lock is to be created (as the Qt for Embedded Linux server does); if \a
    create is false the lock should exist already (as the Qt for Embedded Linux
    client expects).
*/
QLock::QLock(const QString &filename, char id, bool create)
{
    data = new QLockData;
    data->count = 0;
#if defined(QT_NO_SEMAPHORE)
    data->file = filename.toLocal8Bit() + id;
    for (int x = 0; x < 2; ++x) {
        data->id = QT_OPEN(data->file.constData(), O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
        if (data->id != -1 || !create) {
            data->owned = x;
            break;
        }
    }
#elif !defined(QT_POSIX_IPC)
    key_t semkey = ftok(filename.toLocal8Bit().constData(), id);
    data->id = semget(semkey, 0, 0);
    data->owned = create;
    if (create) {
        qt_semun arg;
        arg.val = 0;
        if (data->id != -1)
            semctl(data->id, 0, IPC_RMID, arg);
        data->id = semget(semkey, 1, IPC_CREAT | 0600);
        arg.val = MAX_LOCKS;
        semctl(data->id, 0, SETVAL, arg);
    }
#else
    data->file = filename.toLocal8Bit() + id;
    data->owned = create;

    char ids[3] = { 'c', 'r', 'w' };
    sem_t **sems[3] = { &data->id, &data->rsem, &data->wsem };
    unsigned short initialValues[3] = { MAX_LOCKS, 1, 1 };
    for (int i = 0; i < 3; ++i) {
        QByteArray file = data->file + ids[i];
        do {
            *sems[i] = sem_open(file.constData(), 0, 0666, 0);
        } while (*sems[i] == SEM_FAILED && errno == EINTR);
        if (create) {
            if (*sems[i] != SEM_FAILED) {
                sem_close(*sems[i]);
                sem_unlink(file.constData());
            }
            do {
                *sems[i] = sem_open(file.constData(), O_CREAT, 0666, initialValues[i]);
            } while (*sems[i] == SEM_FAILED && errno == EINTR);
        }
    }
#endif
    if (!isValid()) {
        qWarning("QLock::QLock: Cannot %s semaphore %s '%c' (%d, %s)",
                 (create ? "create" : "get"), qPrintable(filename), id,
                 errno, strerror(errno));
    }

#ifndef QT_NO_QWS_SIGNALHANDLER
    QWSSignalHandler::instance()->addLock(this);
#endif
}
Exemplo n.º 10
0
static int openTtyDevice(const QString &device)
{
    const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };

    int fd = -1;
    if (device.isEmpty()) {
        for (const char * const *dev = devs; *dev; ++dev) {
            fd = QT_OPEN(*dev, O_RDWR);
            if (fd != -1)
                break;
        }
    } else {
        fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);
    }

    return fd;
}
Exemplo n.º 11
0
E60KbdHandler::E60KbdHandler(const QString &device)
{
    qDebug() << "Loaded E60 keyboard plugin!";
    setObjectName("E60 Keypad Handler");
    kbdFd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY, 0);
    if (kbdFd >= 0) {
        qDebug() << "Opened" << device << "as keyboard input";
        m_notify = new QSocketNotifier(kbdFd, QSocketNotifier::Read, this);
        connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKbdData()));
    } else {
void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
{
#ifndef QT_FONTS_ARE_RESOURCES
    struct stat st;
    if (stat(file.constData(), &st))
        return;
    int f = QT_OPEN(file, O_RDONLY, 0);
    if (f < 0)
        return;
    const uchar *data = (const uchar *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, f, 0);
    const int dataSize = st.st_size;
#else
    QResource res(QLatin1String(file.constData()));
    const uchar *data = res.data();
    const int dataSize = res.size();
    //qDebug() << "addQPF2File" << file << data;
#endif
    if (data && data != (const uchar *)MAP_FAILED) {
        if (QFontEngineQPF::verifyHeader(data, dataSize)) {
            QString fontName = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_FontName).toString();
            int pixelSize = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_PixelSize).toInt();
            QVariant weight = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_Weight);
            QVariant style = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_Style);
            QByteArray writingSystemBits = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_WritingSystems).toByteArray();

            if (!fontName.isEmpty() && pixelSize) {
                int fontWeight = 50;
                if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt)
                    fontWeight = weight.toInt();

                bool italic = static_cast<QFont::Style>(style.toInt()) & QFont::StyleItalic;

                QList<QFontDatabase::WritingSystem> writingSystems;
                for (int i = 0; i < writingSystemBits.count(); ++i) {
                    uchar currentByte = writingSystemBits.at(i);
                    for (int j = 0; j < 8; ++j) {
                        if (currentByte & 1)
                            writingSystems << QFontDatabase::WritingSystem(i * 8 + j);
                        currentByte >>= 1;
                    }
                }

                addFont(fontName, /*foundry*/ "prerendered", fontWeight, italic,
                        pixelSize, file, /*fileIndex*/ 0,
                        /*antialiased*/ true, writingSystems);
            }
        } else {
Exemplo n.º 13
0
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
    : m_notify(0), m_fd(-1), d(0)
{
    setObjectName(QLatin1String("Linux Touch Handler"));

    QString dev = QLatin1String("/dev/input/event5");
    try_udev(&dev);

    QStringList args = spec.split(QLatin1Char(':'));
    for (int i = 0; i < args.count(); ++i)
        if (args.at(i).startsWith(QLatin1String("/dev/")))
            dev = args.at(i);

    qDebug("Using device '%s'", qPrintable(dev));
    m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);

    if (m_fd >= 0) {
        m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
        connect(m_notify, SIGNAL(activated(int)), this, SLOT(readData()));
    } else {
Exemplo n.º 14
0
QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &spec, QObject *parent)
    : QObject(parent), m_notify(0), m_fd(-1), d(0)
#ifdef USE_MTDEV
      , m_mtdev(0)
#endif
{
    setObjectName(QLatin1String("Evdev Touch Handler"));

    QString dev;

    // only the first device argument is used for now
    QStringList args = spec.split(QLatin1Char(':'));
    for (int i = 0; i < args.count(); ++i) {
        if (args.at(i).startsWith(QLatin1String("/dev/"))) {
            dev = args.at(i);
            break;
        }
    }

    if (dev.isEmpty()) {
        // try to let udev scan for already connected devices
        QScopedPointer<QDeviceDiscovery> deviceDiscovery(QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this));
        if (deviceDiscovery) {
            QStringList devices = deviceDiscovery->scanConnectedDevices();

            // only the first device found is used for now
            if (devices.size() > 0)
                dev = devices[0];
        }
    }

    if (dev.isEmpty())
        return;

    qDebug("evdevtouch: Using device %s", qPrintable(dev));
    m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);

    if (m_fd >= 0) {
        m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
        connect(m_notify, SIGNAL(activated(int)), this, SLOT(readData()));
    } else {
Exemplo n.º 15
0
static int getTracks(const char *fname, int *tracks)
{
    KISOFUNC;
    int ret = 0;
    memset(tracks, 0, 200*sizeof(int));

#ifdef Q_OS_LINUX
    int fd, i;
    struct cdrom_tochdr tochead;
    struct cdrom_tocentry tocentry;

    //qDebug() << "getTracks open:" << fname << endl;
    fd = QT_OPEN(fname, O_RDONLY | O_NONBLOCK);
    if (fd > 0) {
        if (ioctl(fd, CDROMREADTOCHDR, &tochead) != -1) {
//            qDebug() << "getTracks first track:" << tochead.cdth_trk0
//            << " last track " << tochead.cdth_trk1 << endl;
            for (i = tochead.cdth_trk0;i <= tochead.cdth_trk1;++i) {
                if (ret > 99) break;
                memset(&tocentry, 0, sizeof(struct cdrom_tocentry));
                tocentry.cdte_track = i;
                tocentry.cdte_format = CDROM_LBA;
                if (ioctl(fd, CDROMREADTOCENTRY, &tocentry) < 0) break;
//                qDebug() << "getTracks got track " << i << " starting at: " <<
//                tocentry.cdte_addr.lba << endl;
                if ((tocentry.cdte_ctrl & 0x4) == 0x4) {
                    tracks[ret<<1] = tocentry.cdte_addr.lba;
                    tracks[(ret<<1)+1] = i;
                    ret++;
                }
            }
        }
        close(fd);
    }

#endif

    return ret;
}
Exemplo n.º 16
0
    bool registerSelf(const QString &f) {
        bool fromMM = false;
        uchar *data = 0;
        unsigned int data_len = 0;

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

        int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
#if defined(Q_OS_WIN)
                         _S_IREAD | _S_IWRITE
#else
                         0666
#endif
            );
        if (fd >= 0) {
            QT_STATBUF st;
            if (!QT_FSTAT(fd, &st)) {
                uchar *ptr;
                ptr = reinterpret_cast<uchar *>(
                    mmap(0, st.st_size,             // any address, whole file
                         PROT_READ,                 // read-only memory
                         MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                         fd, 0));                   // from offset 0 of fd
                if (ptr && ptr != reinterpret_cast<uchar *>(MAP_FAILED)) {
                    data = ptr;
                    data_len = st.st_size;
                    fromMM = true;
                }
            }
            ::close(fd);
        }
#endif // QT_USE_MMAP
        if(!data) {
            QFile file(f);
            if (!file.exists())
                return false;
            data_len = file.size();
            data = new uchar[data_len];

            bool ok = false;
            if (file.open(QIODevice::ReadOnly))
                ok = (data_len == (uint)file.read((char*)data, data_len));
            if (!ok) {
                delete [] data;
                data = 0;
                data_len = 0;
                return false;
            }
            fromMM = false;
        }
        if(data && QDynamicBufferResourceRoot::registerSelf(data)) {
            if(fromMM) {
                unmapPointer = data;
                unmapLength = data_len;
            }
            fileName = f;
            return true;
        }
        return false;
    }
Exemplo n.º 17
0
/*!
    \internal

    Generates a unique file path and returns a native handle to the open file.
    \a path is used as a template when generating unique paths, \a pos
    identifies the position of the first character that will be replaced in the
    template and \a length the number of characters that may be substituted.

    Returns an open handle to the newly created file if successful, an invalid
    handle otherwise. In both cases, the string in \a path will be changed and
    contain the generated path name.
*/
static bool createFileFromTemplate(NativeFileHandle &file,
        QFileSystemEntry::NativePath &path, size_t pos, size_t length,
        QSystemError &error)
{
    Q_ASSERT(length != 0);
    Q_ASSERT(pos < size_t(path.length()));
    Q_ASSERT(length <= size_t(path.length()) - pos);

    Char *const placeholderStart = (Char *)path.data() + pos;
    Char *const placeholderEnd = placeholderStart + length;

    // Initialize placeholder with random chars + PID.
    {
        Char *rIter = placeholderEnd;

#if defined(QT_BUILD_CORE_LIB)
        quint64 pid = quint64(QCoreApplication::applicationPid());
        do {
            *--rIter = Latin1Char((pid % 10) + '0');
            pid /= 10;
        } while (rIter != placeholderStart && pid != 0);
#endif

        while (rIter != placeholderStart) {
            char ch = char((qrand() & 0xffff) % (26 + 26));
            if (ch < 26)
                *--rIter = Latin1Char(ch + 'A');
            else
                *--rIter = Latin1Char(ch - 26 + 'a');
        }
    }

    for (;;) {
        // Atomically create file and obtain handle
#if defined(Q_OS_WIN)
#  ifndef Q_OS_WINRT
        file = CreateFile((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
                FILE_ATTRIBUTE_NORMAL, NULL);
#  else // !Q_OS_WINRT
        file = CreateFile2((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW,
                NULL);
#  endif // Q_OS_WINRT

        if (file != INVALID_HANDLE_VALUE)
            return true;

        DWORD err = GetLastError();
        if (err == ERROR_ACCESS_DENIED) {
            WIN32_FILE_ATTRIBUTE_DATA attributes;
            if (!GetFileAttributesEx((const wchar_t *)path.constData(),
                                     GetFileExInfoStandard, &attributes)
                    || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
                // Potential write error (read-only parent directory, etc.).
                error = QSystemError(err, QSystemError::NativeError);
                return false;
            } // else file already exists as a directory.
        } else if (err != ERROR_FILE_EXISTS) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#else // POSIX
        file = QT_OPEN(path.constData(),
                QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
                0600);

        if (file != -1)
            return true;

        int err = errno;
        if (err != EEXIST) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#endif

        /* tricky little algorwwithm for backward compatibility */
        for (Char *iter = placeholderStart;;) {
            // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
            // String progression: "ZZaiC" => "aabiC"
            switch (char(*iter)) {
                case 'Z':
                    // Rollover, advance next character
                    *iter = Latin1Char('a');
                    if (++iter == placeholderEnd) {
                        // Out of alternatives. Return file exists error, previously set.
                        error = QSystemError(err, QSystemError::NativeError);
                        return false;
                    }

                    continue;

                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    *iter = Latin1Char('a');
                    break;

                case 'z':
                    // increment 'z' to 'A'
                    *iter = Latin1Char('A');
                    break;

                default:
                    ++*iter;
                    break;
            }
            break;
        }
    }

    Q_ASSERT(false);
}
Exemplo n.º 18
0
bool QTranslator::load(const QString & filename, const QString & directory,
                       const QString & search_delimiters,
                       const QString & suffix)
{
    Q_D(QTranslator);
    d->clear();

    QString prefix;
    if (QFileInfo(filename).isRelative()) {
        prefix = directory;
	if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
	    prefix += QLatin1Char('/');
    }

    QString fname = filename;
    QString realname;
    QString delims;
    delims = search_delimiters.isNull() ? QString::fromLatin1("_.") : search_delimiters;

    for (;;) {
        QFileInfo fi;

        realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix);
        fi.setFile(realname);
        if (fi.isReadable() && fi.isFile())
            break;

        realname = prefix + fname;
        fi.setFile(realname);
        if (fi.isReadable() && fi.isFile())
            break;

        int rightmost = 0;
        for (int i = 0; i < (int)delims.length(); i++) {
            int k = fname.lastIndexOf(delims[i]);
            if (k > rightmost)
                rightmost = k;
        }

        // no truncations? fail
        if (rightmost == 0)
            return false;

        fname.truncate(rightmost);
    }

    // realname is now the fully qualified name of a readable file.

    bool ok = false;

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

    int fd = -1;
    if (!realname.startsWith(QLatin1Char(':')))
        fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
#if defined(Q_OS_WIN)
                     _S_IREAD | _S_IWRITE
#else
                     0666
#endif
            );
    if (fd >= 0) {
        QT_STATBUF st;
        if (!QT_FSTAT(fd, &st)) {
            char *ptr;
            ptr = reinterpret_cast<char *>(
                mmap(0, st.st_size,             // any address, whole file
                     PROT_READ,                 // read-only memory
                     MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                     fd, 0));                   // from offset 0 of fd
            if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
                d->used_mmap = true;
                d->unmapPointer = ptr;
                d->unmapLength = st.st_size;
                ok = true;
            }
        }
        ::close(fd);
    }
#endif // QT_USE_MMAP

    if (!ok) {
        QFile file(realname);
        d->unmapLength = file.size();
        if (!d->unmapLength)
            return false;
        d->unmapPointer = new char[d->unmapLength];

        if (file.open(QIODevice::ReadOnly))
            ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));

        if (!ok) {
            delete [] d->unmapPointer;
            d->unmapPointer = 0;
            d->unmapLength = 0;
            return false;
        }
    }

    return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}
Exemplo n.º 19
0
bool QTranslatorPrivate::do_load(const QString &realname)
{
    QTranslatorPrivate *d = this;
    bool ok = false;

    const bool isResourceFile = realname.startsWith(QLatin1Char(':'));
    if (isResourceFile) {
        // If the translation is in a non-compressed resource file, the data is already in
        // memory, so no need to use QFile to copy it again.
        Q_ASSERT(!d->resource);
        d->resource = new QResource(realname);
        if (d->resource->isValid() && !d->resource->isCompressed()) {
            d->unmapLength = d->resource->size();
            d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(d->resource->data()));
            d->used_mmap = false;
            ok = true;
        } else {
            delete d->resource;
            d->resource = 0;
        }
    }

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

    else {
        int fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
#if defined(Q_OS_WIN)
                     _S_IREAD | _S_IWRITE
#else
                     0666
#endif
            );

        if (fd >= 0) {
            QT_STATBUF st;
            if (!QT_FSTAT(fd, &st)) {
                char *ptr;
                ptr = reinterpret_cast<char *>(
                    mmap(0, st.st_size,             // any address, whole file
                         PROT_READ,                 // read-only memory
                         MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                         fd, 0));                   // from offset 0 of fd
                if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
                    d->used_mmap = true;
                    d->unmapPointer = ptr;
                    d->unmapLength = st.st_size;
                    ok = true;
                }
            }
            ::close(fd);
        }
    }
#endif // QT_USE_MMAP

    if (!ok) {
        QFile file(realname);
        d->unmapLength = file.size();
        if (!d->unmapLength)
            return false;
        d->unmapPointer = new char[d->unmapLength];

        if (file.open(QIODevice::ReadOnly))
            ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));

        if (!ok) {
            delete [] d->unmapPointer;
            d->unmapPointer = 0;
            d->unmapLength = 0;
            return false;
        }
    }

    return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}
Exemplo n.º 20
0
bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device)
{
    int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
    if (Q_UNLIKELY(fd == -1)) {
        qWarning() << "Device discovery cannot open device" << device;
        return false;
    }

    qCDebug(lcDD) << "doing static device discovery for " << device;

    if ((m_types & Device_DRM) && device.contains(QLatin1String(QT_DRM_DEVICE_PREFIX))) {
        QT_CLOSE(fd);
        return true;
    }

    long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
    long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
    long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
    memset(bitsAbs, 0, sizeof(bitsAbs));
    memset(bitsKey, 0, sizeof(bitsKey));
    memset(bitsRel, 0, sizeof(bitsRel));

    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs);
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel);

    QT_CLOSE(fd);

    if ((m_types & Device_Keyboard)) {
        if (testBit(KEY_Q, bitsKey)) {
            qCDebug(lcDD) << "Found keyboard at" << device;
            return true;
        }
    }

    if ((m_types & Device_Mouse)) {
        if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
            qCDebug(lcDD) << "Found mouse at" << device;
            return true;
        }
    }

    if ((m_types & (Device_Touchpad | Device_Touchscreen))) {
        if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
            if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
                qCDebug(lcDD) << "Found touchpad at" << device;
                return true;
            } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
                qCDebug(lcDD) << "Found touchscreen at" << device;
                return true;
            } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) {
                qCDebug(lcDD) << "Found tablet at" << device;
                return true;
            }
        } else if (testBit(ABS_MT_POSITION_X, bitsAbs) &&
                   testBit(ABS_MT_POSITION_Y, bitsAbs)) {
            qCDebug(lcDD) << "Found new-style touchscreen at" << device;
            return true;
        }
    }

    if ((m_types & Device_Joystick)) {
        if (testBit(BTN_A, bitsKey) || testBit(BTN_TRIGGER, bitsKey) || testBit(ABS_RX, bitsAbs)) {
            qCDebug(lcDD) << "Found joystick/gamepad at" << device;
            return true;
        }
    }

    return false;
}
Exemplo n.º 21
0
bool QLinuxFbScreen::connect(const QString &displaySpec)
{
    d_ptr->displaySpec = displaySpec;

    const QStringList args = displaySpec.split(QLatin1Char(':'));

    if (args.contains(QLatin1String("nographicsmodeswitch")))
        d_ptr->doGraphicsMode = false;

#ifdef QT_QWS_DEPTH_GENERIC
    if (args.contains(QLatin1String("genericcolors")))
        d_ptr->doGenericColors = true;
#endif

    QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
    if (args.indexOf(ttyRegExp) != -1)
        d_ptr->ttyDevice = ttyRegExp.cap(1);

#if Q_BYTE_ORDER == Q_BIG_ENDIAN
#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
    if (args.contains(QLatin1String("littleendian")))
#endif
        QScreen::setFrameBufferLittleEndian(true);
#endif

    QString dev = QLatin1String("/dev/fb0");
    foreach(QString d, args) {
	if (d.startsWith(QLatin1Char('/'))) {
	    dev = d;
	    break;
	}
    }

    if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
        d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
    if (d_ptr->fd == -1) {
        if (QApplication::type() == QApplication::GuiServer) {
            perror("QScreenLinuxFb::connect");
            qCritical("Error opening framebuffer device %s", qPrintable(dev));
            return false;
        }
        if (access(dev.toLatin1().constData(), R_OK) == 0)
            d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
    }

    ::fb_fix_screeninfo finfo;
    ::fb_var_screeninfo vinfo;
    //#######################
    // Shut up Valgrind
    memset(&vinfo, 0, sizeof(vinfo));
    memset(&finfo, 0, sizeof(finfo));
    //#######################

    /* Get fixed screen information */
    if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
        perror("QLinuxFbScreen::connect");
        qWarning("Error reading fixed information");
        return false;
    }

    d_ptr->driverType = strcmp(finfo.id, "8TRACKFB") ? GenericDriver : EInk8Track;

    if (finfo.type == FB_TYPE_VGA_PLANES) {
        qWarning("VGA16 video mode not supported");
        return false;
    }

    /* Get variable screen information */
    if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
        perror("QLinuxFbScreen::connect");
        qWarning("Error reading variable information");
        return false;
    }

    fixupScreenInfo(finfo, vinfo);

    grayscale = vinfo.grayscale;
    d = vinfo.bits_per_pixel;
    if (d == 24) {
        d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
        if (d <= 0)
            d = 24; // reset if color component lengths are not reported
    } else if (d == 16) {
        d = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
        if (d <= 0)
            d = 16;
    }
    lstep = finfo.line_length;

    int xoff = vinfo.xoffset;
    int yoff = vinfo.yoffset;
    const char* qwssize;
    if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) {
        if (d_ptr->fd != -1) {
            if ((uint)w > vinfo.xres) w = vinfo.xres;
            if ((uint)h > vinfo.yres) h = vinfo.yres;
        }
        dw=w;
        dh=h;
        int xxoff, yyoff;
        if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) {
            if (xxoff < 0 || xxoff + w > vinfo.xres)
                xxoff = vinfo.xres - w;
            if (yyoff < 0 || yyoff + h > vinfo.yres)
                yyoff = vinfo.yres - h;
            xoff += xxoff;
            yoff += yyoff;
        } else {
            xoff += (vinfo.xres - w)/2;
            yoff += (vinfo.yres - h)/2;
        }
    } else {
        dw=w=vinfo.xres;
        dh=h=vinfo.yres;
    }

    if (w == 0 || h == 0) {
        qWarning("QScreenLinuxFb::connect(): Unable to find screen geometry, "
                 "will use 320x240.");
        dw = w = 320;
        dh = h = 240;
    }

    setPixelFormat(vinfo);

    // Handle display physical size spec.
    QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
    QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
    int dimIdxW = displayArgs.indexOf(mmWidthRx);
    QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
    int dimIdxH = displayArgs.indexOf(mmHeightRx);
    if (dimIdxW >= 0) {
        mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
        physWidth = mmWidthRx.cap(1).toInt();
        if (dimIdxH < 0)
            physHeight = dh*physWidth/dw;
    }
    if (dimIdxH >= 0) {
        mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
        physHeight = mmHeightRx.cap(1).toInt();
        if (dimIdxW < 0)
            physWidth = dw*physHeight/dh;
    }
    if (dimIdxW < 0 && dimIdxH < 0) {
        if (vinfo.width != 0 && vinfo.height != 0
            && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
            physWidth = vinfo.width;
            physHeight = vinfo.height;
        } else {
            const int dpi = 72;
            physWidth = qRound(dw * 25.4 / dpi);
            physHeight = qRound(dh * 25.4 / dpi);
        }
    }

    dataoffset = yoff * lstep + xoff * d / 8;
    //qDebug("Using %dx%dx%d screen",w,h,d);

    /* Figure out the size of the screen in bytes */
    size = h * lstep;

    mapsize = finfo.smem_len;

    data = (unsigned char *)-1;
    if (d_ptr->fd != -1)
        data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE,
                                     MAP_SHARED, d_ptr->fd, 0);

    if ((long)data == -1) {
        if (QApplication::type() == QApplication::GuiServer) {
            perror("QLinuxFbScreen::connect");
            qWarning("Error: failed to map framebuffer device to memory.");
            return false;
        }
        data = 0;
    } else {
        data += dataoffset;
    }

    canaccel = useOffscreen();
    if(canaccel)
        setupOffScreen();

    // Now read in palette
    if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
        screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
        int loopc;
        ::fb_cmap startcmap;
        startcmap.start=0;
        startcmap.len=screencols;
        startcmap.red=(unsigned short int *)
                 malloc(sizeof(unsigned short int)*screencols);
        startcmap.green=(unsigned short int *)
                   malloc(sizeof(unsigned short int)*screencols);
        startcmap.blue=(unsigned short int *)
                  malloc(sizeof(unsigned short int)*screencols);
        startcmap.transp=(unsigned short int *)
                    malloc(sizeof(unsigned short int)*screencols);
        if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) {
            perror("QLinuxFbScreen::connect");
            qWarning("Error reading palette from framebuffer, using default palette");
            createPalette(startcmap, vinfo, finfo);
        }
        int bits_used = 0;
        for(loopc=0;loopc<screencols;loopc++) {
            screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8,
                                   startcmap.green[loopc] >> 8,
                                   startcmap.blue[loopc] >> 8);
            bits_used |= startcmap.red[loopc]
                         | startcmap.green[loopc]
                         | startcmap.blue[loopc];
        }
        // WORKAROUND: Some framebuffer drivers only return 8 bit
        // color values, so we need to not bit shift them..
        if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) {
            for(loopc=0;loopc<screencols;loopc++) {
                screenclut[loopc] = qRgb(startcmap.red[loopc],
                                         startcmap.green[loopc],
                                         startcmap.blue[loopc]);
            }
            qWarning("8 bits cmap returned due to faulty FB driver, colors corrected");
        }
        free(startcmap.red);
        free(startcmap.green);
        free(startcmap.blue);
        free(startcmap.transp);
    } else {
Exemplo n.º 22
0
/*!
    \internal
*/
bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
{
    Q_Q(QFSFileEngine);

    if (openMode & QIODevice::Unbuffered) {
        int flags = openModeToOpenFlags(openMode);

        // Try to open the file in unbuffered mode.
        do {
            fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
        } while (fd == -1 && errno == EINTR);

        // On failure, return and report the error.
        if (fd == -1) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(errno));
            return false;
        }

        if (!(openMode & QIODevice::WriteOnly)) {
            // we don't need this check if we tried to open for writing because then
            // we had received EISDIR anyway.
            if (QFileSystemEngine::fillMetaData(fd, metaData)
                    && metaData.isDirectory()) {
                q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
                QT_CLOSE(fd);
                return false;
            }
        }

        // Seek to the end when in Append mode.
        if (flags & QFile::Append) {
            int ret;
            do {
                ret = QT_LSEEK(fd, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fh = 0;
    } else {
        QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);

        // Try to open the file in buffered mode.
        do {
            fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
        } while (!fh && errno == EINTR);

        // On failure, return and report the error.
        if (!fh) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(int(errno)));
            return false;
        }

        if (!(openMode & QIODevice::WriteOnly)) {
            // we don't need this check if we tried to open for writing because then
            // we had received EISDIR anyway.
            if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
                    && metaData.isDirectory()) {
                q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
                fclose(fh);
                return false;
            }
        }

        setCloseOnExec(fileno(fh)); // ignore failure

        // Seek to the end when in Append mode.
        if (openMode & QIODevice::Append) {
            int ret;
            do {
                ret = QT_FSEEK(fh, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fd = -1;
    }

    closeFileHandle = true;
    return true;
}
Exemplo n.º 23
0
/*!
    \internal
*/
bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
{
    Q_Q(QFSFileEngine);

    if (openMode & QIODevice::Unbuffered) {
        int flags = openModeToOpenFlags(openMode);

        // Try to open the file in unbuffered mode.
        do {
            fd = QT_OPEN(nativeFilePath.constData(), flags, 0666);
        } while (fd == -1 && errno == EINTR);

        // On failure, return and report the error.
        if (fd == -1) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(errno));
            return false;
        }

#ifndef O_CLOEXEC
        // not needed on Linux >= 2.6.23
        setCloseOnExec(fd);     // ignore failure
#endif

        // Seek to the end when in Append mode.
        if (flags & QFile::Append) {
            int ret;
            do {
                ret = QT_LSEEK(fd, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fh = 0;
    } else {
        QByteArray fopenMode = openModeToFopenMode(openMode, filePath);

        // Try to open the file in buffered mode.
        do {
            fh = QT_FOPEN(nativeFilePath.constData(), fopenMode.constData());
        } while (!fh && errno == EINTR);

        // On failure, return and report the error.
        if (!fh) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(int(errno)));
            return false;
        }

        setCloseOnExec(fileno(fh)); // ignore failure

        // Seek to the end when in Append mode.
        if (openMode & QIODevice::Append) {
            int ret;
            do {
                ret = QT_FSEEK(fh, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fd = -1;
    }

    closeFileHandle = true;
    return true;
}
Exemplo n.º 24
0
/*!
    \internal

    Generates a unique file path and returns a native handle to the open file.
    \a path is used as a template when generating unique paths, \a pos
    identifies the position of the first character that will be replaced in the
    template and \a length the number of characters that may be substituted.

    Returns an open handle to the newly created file if successful, an invalid
    handle otherwise. In both cases, the string in \a path will be changed and
    contain the generated path name.
*/
static bool createFileFromTemplate(NativeFileHandle &file,
        QFileSystemEntry::NativePath &path, size_t pos, size_t length,
        QSystemError &error)
{
    Q_ASSERT(length != 0);
    Q_ASSERT(pos < size_t(path.length()));
    Q_ASSERT(length <= size_t(path.length()) - pos);

    Char *const placeholderStart = (Char *)path.data() + pos;
    Char *const placeholderEnd = placeholderStart + length;

    // Initialize placeholder with random chars + PID.
    {
        Char *rIter = placeholderEnd;

#if defined(QT_BUILD_CORE_LIB)
        quint64 pid = quint64(QCoreApplication::applicationPid());
        do {
            *--rIter = Latin1Char((pid % 10) + '0');
            pid /= 10;
        } while (rIter != placeholderStart && pid != 0);
#endif

        while (rIter != placeholderStart) {
            char ch = char((qrand() & 0xffff) % (26 + 26));
            if (ch < 26)
                *--rIter = Latin1Char(ch + 'A');
            else
                *--rIter = Latin1Char(ch - 26 + 'a');
        }
    }

#ifdef Q_OS_SYMBIAN
    RFs& fs = qt_s60GetRFs();
#endif

    for (;;) {
        // Atomically create file and obtain handle
#if defined(Q_OS_WIN)
        file = CreateFile((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
                FILE_ATTRIBUTE_NORMAL, NULL);

        if (file != INVALID_HANDLE_VALUE)
            return true;

        DWORD err = GetLastError();
        if (err != ERROR_FILE_EXISTS) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#elif defined(Q_OS_SYMBIAN)
        TInt err = file.Create(fs, qt_QString2TPtrC(path),
                EFileRead | EFileWrite | EFileShareReadersOrWriters);

        if (err == KErrNone)
            return true;

        if (err != KErrAlreadyExists) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#else // POSIX
        file = QT_OPEN(path.constData(),
                QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
                0600);

        if (file != -1)
            return true;

        int err = errno;
        if (err != EEXIST) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#endif

        /* tricky little algorwwithm for backward compatibility */
        for (Char *iter = placeholderStart;;) {
            // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
            // String progression: "ZZaiC" => "aabiC"
            switch (char(*iter)) {
                case 'Z':
                    // Rollover, advance next character
                    *iter = Latin1Char('a');
                    if (++iter == placeholderEnd) {
                        // Out of alternatives. Return file exists error, previously set.
                        error = QSystemError(err, QSystemError::NativeError);
                        return false;
                    }

                    continue;

                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    *iter = Latin1Char('a');
                    break;

                case 'z':
                    // increment 'z' to 'A'
                    *iter = Latin1Char('A');
                    break;

                default:
                    ++*iter;
                    break;
            }
            break;
        }
    }

    Q_ASSERT(false);
}