1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/***************************************************************************
* Copyright (C) 2008 by Alexander Block *
* ablock@blocksoftware.net *
* *
* 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 program 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. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "config.h"
#include "shm.h"
#include "buf.h"
#include "error.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
struct shm_header
{
int buf_size;
};
/////////////
int hexec_shm_create(struct hexec_shm* shm, const char* shm_name, struct hexec_buf* buf)
{
int fd = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG);
if(fd == -1)
{
hexec_error("failed to create shared memory object %s\n", shm_name);
return -1;
}
int mmap_size = sizeof(struct shm_header) + buf->buf_size;
if(ftruncate(fd, mmap_size))
{
close(fd);
shm_unlink(shm_name);
hexec_error("failed to resize shared memory object %s\n", shm_name);
return -1;
}
char* mmap_buf = mmap(NULL, mmap_size, PROT_WRITE, MAP_SHARED, fd, 0);
if(mmap_buf == MAP_FAILED)
{
close(fd);
shm_unlink(shm_name);
hexec_error("failed to map shared memory object %s\n", shm_name);
return -1;
}
struct shm_header header;
header.buf_size = buf->buf_size;
memcpy(mmap_buf, &header, sizeof(struct shm_header));
hexec_buf_copy_to(buf, mmap_buf + sizeof(struct shm_header), buf->buf_size);
close(fd);
shm->owner = true;
shm->name = strdup(shm_name);
shm->mmap = mmap_buf;
shm->mmap_size = mmap_size;
shm->buf = mmap_buf + sizeof(struct shm_header);
shm->buf_size = buf->buf_size;
return 0;
}
int hexec_shm_open(struct hexec_shm* shm, const char* shm_name)
{
int fd = shm_open(shm_name, O_RDONLY, 0);
if(fd == -1)
{
hexec_error("failed to open shared memory object %s\n", shm_name);
return -1;
}
char* mmap_buf = mmap(NULL, sizeof(struct shm_header), PROT_READ, MAP_SHARED, fd, 0);
if(mmap_buf == MAP_FAILED)
{
close(fd);
hexec_error("failed to map shared memory object %s\n", shm_name);
return -1;
}
struct shm_header header;
memcpy(&header, mmap_buf, sizeof(struct shm_header));
munmap(mmap_buf, sizeof(struct shm_header));
int mmap_size = sizeof(struct shm_header) + header.buf_size;
mmap_buf = mmap(NULL, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
if(mmap_buf == MAP_FAILED)
{
close(fd);
hexec_error("failed to map shared memory object %s\n", shm_name);
return -1;
}
close(fd);
shm->owner = false;
shm->name = strdup(shm_name);
shm->mmap = mmap_buf;
shm->mmap_size = mmap_size;
shm->buf = mmap_buf + sizeof(struct shm_header);
shm->buf_size = header.buf_size;
return 0;
}
int hexec_shm_close(struct hexec_shm* shm)
{
if(munmap(shm->mmap, shm->mmap_size))
hexec_fatal("failed to unmap shared memory object %s\n", shm->name);
if(shm->owner && shm_unlink(shm->name))
hexec_fatal("failed to unlink shared memory object %s\n", shm->name);
free(shm->name);
return 0;
}
int hexec_shm_to_buf(struct hexec_shm* shm, struct hexec_buf* buf)
{
return hexec_buf_create_from(buf, shm->buf, shm->buf_size, false);
}
|