Home | History | Annotate | Download | only in qemu_pipe
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "qemu_pipe.h"
     18 
     19 #include <unistd.h>
     20 #include <fcntl.h>
     21 #include <string.h>
     22 #include <errno.h>
     23 #include <stdio.h>
     24 
     25 #include <android-base/file.h>
     26 
     27 using android::base::ReadFully;
     28 using android::base::WriteFully;
     29 
     30 // Define QEMU_PIPE_DEBUG if you want to print error messages when an error
     31 // occurs during pipe operations. The macro should simply take a printf-style
     32 // formatting string followed by optional arguments.
     33 #ifndef QEMU_PIPE_DEBUG
     34 #  define  QEMU_PIPE_DEBUG(...)   (void)0
     35 #endif
     36 
     37 int qemu_pipe_open(const char* pipeName) {
     38     // Sanity check.
     39     if (!pipeName) {
     40         errno = EINVAL;
     41         return -1;
     42     }
     43 
     44     int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
     45     if (fd < 0) {
     46         QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
     47                         strerror(errno));
     48         return -1;
     49     }
     50 
     51     // Write the pipe name, *including* the trailing zero which is necessary.
     52     size_t pipeNameLen = strlen(pipeName);
     53     if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
     54         return fd;
     55     }
     56 
     57     // now, add 'pipe:' prefix and try again
     58     // Note: host side will wait for the trailing '\0' to start
     59     // service lookup.
     60     const char pipe_prefix[] = "pipe:";
     61     if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
     62             WriteFully(fd, pipeName, pipeNameLen + 1U)) {
     63         return fd;
     64     }
     65     QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s",
     66             __FUNCTION__, pipeName, strerror(errno));
     67     close(fd);
     68     return -1;
     69 }
     70 
     71 int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
     72     char header[5];
     73     snprintf(header, sizeof(header), "%04zx", len);
     74     if (!WriteFully(fd, header, 4)) {
     75         QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
     76         return -1;
     77     }
     78     if (!WriteFully(fd, buff, len)) {
     79         QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
     80         return -1;
     81     }
     82     return 0;
     83 }
     84 
     85 int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
     86     char header[5];
     87     if (!ReadFully(fd, header, 4)) {
     88         QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
     89         return -1;
     90     }
     91     header[4] = '\0';
     92     size_t size;
     93     if (sscanf(header, "%04zx", &size) != 1) {
     94         QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
     95         return -1;
     96     }
     97     if (size > len) {
     98         QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
     99                         len);
    100         return -1;
    101     }
    102     if (!ReadFully(fd, buff, size)) {
    103         QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
    104                         strerror(errno));
    105         return -1;
    106     }
    107     return size;
    108 }
    109