}
}
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+static bool do_send(int fd, void *data, size_t len, int flags)
+{
+ const size_t CHUNK_SIZE = 1024;
+
+ while (len) {
+ size_t sz = MIN(len, CHUNK_SIZE);
+ ssize_t ret = send(fd, data, sz, flags);
+
+ if (ret == -1) {
+ PRINTERR("Cannot send data, len=%zu, err=%d",
+ sz, errno);
+ break;
+ } else if ((size_t)ret == sz) {
+ len -= sz;
+ data += sz;
+ continue;
+ } else {
+ PRINTERR("Cannot send data, len=%zu, send_len=%zu",
+ sz, ret);
+ break;
+ }
+ }
+
+ return !len;
+}
+
+static void do_msg_send(int fd, enum AppMessageType type,
+ void *data, size_t len)
+{
+ struct msg_header {
+ int type;
+ int length;
+ };
+
+ struct msg_header header = {
+ .type = type,
+ .length = len,
+ };
+
+ do_send(fd, &header, sizeof(header), MSG_NOSIGNAL);
+ do_send(fd, data, len, MSG_NOSIGNAL);
+}
+
+void msg_send(enum AppMessageType type, void *data, size_t len)
+{
+ int fd = gTraceInfo.socket.daemonSock;
+ pthread_mutex_t *mutex = &gTraceInfo.socket.sockMutex;
+
+ if (fd == -1)
+ return;
+
+ real_pthread_mutex_lock(mutex);
+ do_msg_send(fd, type, data, len);
+ real_pthread_mutex_unlock(mutex);
+}
+
+
bool printLog(log_t *log, int msgType)
{
ssize_t res, len;
#include <pthread.h> // for mutex
#include <sys/param.h> // MIN, MAX
#include <sys/mman.h> // mmap
+#include <errno.h>
#include <Ecore.h>
#include <Evas.h>
__current_angle = angle;
}
+
+struct file_data {
+ size_t len;
+ void *data;
+};
+
+static size_t fsize(int fd)
+{
+ struct stat st;
+ if (fstat(fd, &st) != 0)
+ return 0;
+ return st.st_size;
+}
+
+static int do_read_file(int fd, void *data, size_t len)
+{
+ while (len) {
+ ssize_t n = read(fd, data, len);
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+
+ return -errno;
+ } else if (n == 0) {
+ return -EPERM;
+ }
+
+ len -= n;
+ data += n;
+ }
+
+ return 0;
+}
+
+static struct file_data *file_data_create(const char *path)
+{
+ int fd, ret;
+ struct file_data *fdata;
+ const size_t MAX_FILE_SIZE = 32 * 1024 * 1024;
+
+ fdata = malloc(sizeof(*fdata));
+ if (!fdata) {
+ PRINTERR("Out of memory");
+ return NULL;
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ PRINTERR("Cannot open '%s', errno=%d", path, fd);
+ goto free_fdata;
+ }
+
+ fdata->len = fsize(fd);
+ if (!fdata->len) {
+ PRINTERR("Cannot calculate file size, path='%s'", path);
+ goto close_fd;
+ }
+
+ if (fdata->len > MAX_FILE_SIZE) {
+ PRINTERR("file size is very long, len=%zu", fdata->len);
+ goto close_fd;
+ }
+
+ fdata->data = malloc(fdata->len);
+ if (!fdata->data) {
+ PRINTERR("Out of memory");
+ goto close_fd;
+ }
+
+ ret = do_read_file(fd, fdata->data, fdata->len);
+ if (ret) {
+ PRINTERR("Cannot read file, ret=%d", ret);
+ goto free_data;
+ }
+
+ close(fd);
+ return fdata;
+
+free_data:
+ free(fdata->data);
+close_fd:
+ close(fd);
+free_fdata:
+ free(fdata);
+ return NULL;
+}
+
+static void file_data_free(struct file_data *data)
+{
+ free(data->data);
+ free(data);
+}
+
+
+static size_t screenshot_pack_info(char *buf)
+{
+ /* pack probe */
+ PREPARE_LOCAL_BUF_THOUGH(buf);
+ PACK_COMMON_BEGIN(MSG_PROBE_SCREENSHOT, API_ID_captureScreen, "", 0);
+ /* Pack any address, cause this is not an event probe */
+ PACK_COMMON_END_THOUGH('d', 0, 0, 0, 0xffffffff);
+
+ return BUF_PTR - LOCAL_BUF;
+}
+
+static int screenshot_send_to_socket(const char *path)
+{
+ struct file_data *fdata;
+ char sh_info[256];
+ void *buf, *p;
+ size_t sh_info_len, buf_size;
+
+ fdata = file_data_create(path);
+ if (!fdata)
+ return -1;
+
+ /* pack common colums */
+ sh_info_len = screenshot_pack_info(sh_info);
+
+ /* format:
+ *
+ * | sh_info | |
+ * +----+------+-------+---------+
+ * |len | data | angle | img.png |
+ * | 4 | ... | 4 | ... |
+ *
+ */
+ buf_size = 4 + sh_info_len + 4 + fdata->len;
+ buf = malloc(buf_size);
+ if (!buf) {
+ PRINTERR("Out of memory");
+ file_data_free(fdata);
+ return -1;
+ }
+
+ /* pack sh_info */
+ p = pack_int32(buf, sh_info_len);
+ p = pack_bin(p, sh_info, sh_info_len);
+
+ /* pack angle */
+ p = pack_int32(p, current_angle_get());
+
+ /* pack img.png */
+ p = pack_bin(p, fdata->data, fdata->len);
+
+ /* send screenshot to manager */
+ msg_send(APP_MSG_IMAGE, buf, buf_size);
+ file_data_free(fdata);
+
+ return 0;
+}
+
int captureScreen()
{
static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER;
getCurrentEventIndex());
ret = __capture_screnshot_wayland(dstpath);
- if (ret == -EAGAIN)
- ret = __capture_screnshot_wayland(dstpath);
- if (!ret) {
- if (chmod(dstpath, 0777) == -1)
- PRINTWRN("cannot chmod -R777 <%s>", dstpath);
-
- /* welcome to the hell */
- log_t log;
- PREPARE_LOCAL_BUF_THOUGH((char *)&log);
-
- /* skip header */
- LOCAL_BUF += offsetof(log_t, data);
- /* pack screenshot name */
- BUF_PTR = pack_string(LOCAL_BUF, dstpath); /* file name */
- LOCAL_BUF = BUF_PTR;
-
- /* pack probe */
- PACK_COMMON_BEGIN(MSG_PROBE_SCREENSHOT, API_ID_captureScreen, "", 0);
- /* Pack any address, cause this is not an event probe */
- PACK_COMMON_END_THOUGH('d', 0, 0, 0, 0xffffffff);
- PACK_SCREENSHOT(dstpath, current_angle_get());
- SET_MSG_LEN();
- log.length = GET_MSG_LEN() + MSG_HDR_LEN + strlen(dstpath) + 1;
-
- /* send all message */
- printLog(&log, APP_MSG_IMAGE);
- ret = 0;
+ if (ret) {
+ PRINTERR("Cannot capture screenshot, ret=%d", ret);
+ goto unlock;
}
+ ret = screenshot_send_to_socket(dstpath);
+ remove(dstpath);
+
+unlock:
pthread_mutex_unlock(&captureScreenLock);
return ret;
}