Add support for MIT-SHM AttachFd request
This passes a file descriptor from the client to the server, which is then mmap'd Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
parent
9fd35daa31
commit
fdec793cdc
157
Xext/shm.c
157
Xext/shm.c
|
@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group.
|
||||||
#include "xace.h"
|
#include "xace.h"
|
||||||
#include <X11/extensions/shmproto.h>
|
#include <X11/extensions/shmproto.h>
|
||||||
#include <X11/Xfuncproto.h>
|
#include <X11/Xfuncproto.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include "protocol-versions.h"
|
#include "protocol-versions.h"
|
||||||
|
|
||||||
/* Needed for Solaris cross-zone shared memory extension */
|
/* Needed for Solaris cross-zone shared memory extension */
|
||||||
|
@ -382,8 +383,10 @@ ProcShmAttach(ClientPtr client)
|
||||||
client->errorValue = stuff->readOnly;
|
client->errorValue = stuff->readOnly;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
for (shmdesc = Shmsegs;
|
for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) {
|
||||||
shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next);
|
if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (shmdesc) {
|
if (shmdesc) {
|
||||||
if (!stuff->readOnly && !shmdesc->writable)
|
if (!stuff->readOnly && !shmdesc->writable)
|
||||||
return BadAccess;
|
return BadAccess;
|
||||||
|
@ -393,6 +396,7 @@ ProcShmAttach(ClientPtr client)
|
||||||
shmdesc = malloc(sizeof(ShmDescRec));
|
shmdesc = malloc(sizeof(ShmDescRec));
|
||||||
if (!shmdesc)
|
if (!shmdesc)
|
||||||
return BadAlloc;
|
return BadAlloc;
|
||||||
|
shmdesc->is_fd = FALSE;
|
||||||
shmdesc->addr = shmat(stuff->shmid, 0,
|
shmdesc->addr = shmat(stuff->shmid, 0,
|
||||||
stuff->readOnly ? SHM_RDONLY : 0);
|
stuff->readOnly ? SHM_RDONLY : 0);
|
||||||
if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) {
|
if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) {
|
||||||
|
@ -431,6 +435,9 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */
|
||||||
|
|
||||||
if (--shmdesc->refcnt)
|
if (--shmdesc->refcnt)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
if (shmdesc->is_fd)
|
||||||
|
munmap(shmdesc->addr, shmdesc->size);
|
||||||
|
else
|
||||||
shmdt(shmdesc->addr);
|
shmdt(shmdesc->addr);
|
||||||
for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next);
|
for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next);
|
||||||
*prev = shmdesc->next;
|
*prev = shmdesc->next;
|
||||||
|
@ -1087,6 +1094,122 @@ ProcShmCreatePixmap(ClientPtr client)
|
||||||
return BadAlloc;
|
return BadAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcShmAttachFd(ClientPtr client)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
ShmDescPtr shmdesc;
|
||||||
|
REQUEST(xShmAttachFdReq);
|
||||||
|
struct stat statb;
|
||||||
|
|
||||||
|
SetReqFds(client, 1);
|
||||||
|
REQUEST_SIZE_MATCH(xShmAttachFdReq);
|
||||||
|
LEGAL_NEW_RESOURCE(stuff->shmseg, client);
|
||||||
|
if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
|
||||||
|
client->errorValue = stuff->readOnly;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
fd = ReadFdFromClient(client);
|
||||||
|
if (fd < 0)
|
||||||
|
return BadMatch;
|
||||||
|
|
||||||
|
if (fstat(fd, &statb) < 0 || statb.st_size == 0) {
|
||||||
|
close(fd);
|
||||||
|
return BadMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
shmdesc = malloc(sizeof(ShmDescRec));
|
||||||
|
if (!shmdesc) {
|
||||||
|
close(fd);
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
shmdesc->is_fd = TRUE;
|
||||||
|
shmdesc->addr = mmap(NULL, statb.st_size,
|
||||||
|
stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
|
||||||
|
MAP_SHARED,
|
||||||
|
fd, 0);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
if ((shmdesc->addr == ((char *) -1))) {
|
||||||
|
free(shmdesc);
|
||||||
|
return BadAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
shmdesc->refcnt = 1;
|
||||||
|
shmdesc->writable = !stuff->readOnly;
|
||||||
|
shmdesc->size = statb.st_size;
|
||||||
|
shmdesc->next = Shmsegs;
|
||||||
|
Shmsegs = shmdesc;
|
||||||
|
|
||||||
|
if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc))
|
||||||
|
return BadAlloc;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcShmCreateSegment(ClientPtr client)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
ShmDescPtr shmdesc;
|
||||||
|
REQUEST(xShmCreateSegmentReq);
|
||||||
|
xShmCreateSegmentReply rep = {
|
||||||
|
.type = X_Reply,
|
||||||
|
.nfd = 1,
|
||||||
|
.sequenceNumber = client->sequence,
|
||||||
|
.length = 0,
|
||||||
|
};
|
||||||
|
char template[] = "/tmp/shm-XXXXXX";
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
|
||||||
|
if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
|
||||||
|
client->errorValue = stuff->readOnly;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
fd = mkstemp(template);
|
||||||
|
if (fd < 0)
|
||||||
|
return BadAlloc;
|
||||||
|
unlink(template);
|
||||||
|
if (ftruncate(fd, stuff->size) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
shmdesc = malloc(sizeof(ShmDescRec));
|
||||||
|
if (!shmdesc) {
|
||||||
|
close(fd);
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
shmdesc->is_fd = TRUE;
|
||||||
|
shmdesc->addr = mmap(NULL, stuff->size,
|
||||||
|
stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
|
||||||
|
MAP_SHARED,
|
||||||
|
fd, 0);
|
||||||
|
|
||||||
|
if ((shmdesc->addr == ((char *) -1))) {
|
||||||
|
close(fd);
|
||||||
|
free(shmdesc);
|
||||||
|
return BadAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
shmdesc->refcnt = 1;
|
||||||
|
shmdesc->writable = !stuff->readOnly;
|
||||||
|
shmdesc->size = stuff->size;
|
||||||
|
shmdesc->next = Shmsegs;
|
||||||
|
Shmsegs = shmdesc;
|
||||||
|
|
||||||
|
if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) {
|
||||||
|
close(fd);
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WriteFdToClient(client, fd, TRUE) < 0) {
|
||||||
|
FreeResource(stuff->shmseg, RT_NONE);
|
||||||
|
close(fd);
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ProcShmDispatch(ClientPtr client)
|
ProcShmDispatch(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -1116,6 +1239,10 @@ ProcShmDispatch(ClientPtr client)
|
||||||
return ProcPanoramiXShmCreatePixmap(client);
|
return ProcPanoramiXShmCreatePixmap(client);
|
||||||
#endif
|
#endif
|
||||||
return ProcShmCreatePixmap(client);
|
return ProcShmCreatePixmap(client);
|
||||||
|
case X_ShmAttachFd:
|
||||||
|
return ProcShmAttachFd(client);
|
||||||
|
case X_ShmCreateSegment:
|
||||||
|
return ProcShmCreateSegment(client);
|
||||||
default:
|
default:
|
||||||
return BadRequest;
|
return BadRequest;
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1343,28 @@ SProcShmCreatePixmap(ClientPtr client)
|
||||||
return ProcShmCreatePixmap(client);
|
return ProcShmCreatePixmap(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcShmAttachFd(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xShmAttachFdReq);
|
||||||
|
SetReqFds(client, 1);
|
||||||
|
swaps(&stuff->length);
|
||||||
|
REQUEST_SIZE_MATCH(xShmAttachFdReq);
|
||||||
|
swapl(&stuff->shmseg);
|
||||||
|
return ProcShmAttachFd(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcShmCreateSegment(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xShmCreateSegmentReq);
|
||||||
|
swaps(&stuff->length);
|
||||||
|
REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
|
||||||
|
swapl(&stuff->shmseg);
|
||||||
|
swapl(&stuff->size);
|
||||||
|
return ProcShmCreateSegment(client);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SProcShmDispatch(ClientPtr client)
|
SProcShmDispatch(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -1233,6 +1382,10 @@ SProcShmDispatch(ClientPtr client)
|
||||||
return SProcShmGetImage(client);
|
return SProcShmGetImage(client);
|
||||||
case X_ShmCreatePixmap:
|
case X_ShmCreatePixmap:
|
||||||
return SProcShmCreatePixmap(client);
|
return SProcShmCreatePixmap(client);
|
||||||
|
case X_ShmAttachFd:
|
||||||
|
return SProcShmAttachFd(client);
|
||||||
|
case X_ShmCreateSegment:
|
||||||
|
return SProcShmCreateSegment(client);
|
||||||
default:
|
default:
|
||||||
return BadRequest;
|
return BadRequest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ typedef struct _ShmDesc {
|
||||||
int shmid;
|
int shmid;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
char *addr;
|
char *addr;
|
||||||
|
Bool is_fd;
|
||||||
Bool writable;
|
Bool writable;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
} ShmDescRec, *ShmDescPtr;
|
} ShmDescRec, *ShmDescPtr;
|
||||||
|
|
|
@ -100,6 +100,8 @@ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
|
||||||
|
|
||||||
extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
|
extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
|
||||||
|
|
||||||
|
extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close);
|
||||||
|
|
||||||
extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
|
extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
|
||||||
char * /*data */ ,
|
char * /*data */ ,
|
||||||
int /*count */ );
|
int /*count */ );
|
||||||
|
|
8
os/io.c
8
os/io.c
|
@ -506,6 +506,14 @@ ReadFdFromClient(ClientPtr client)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
WriteFdToClient(ClientPtr client, int fd, Bool do_close)
|
||||||
|
{
|
||||||
|
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
||||||
|
|
||||||
|
return _XSERVTransSendFd(oc->trans_conn, fd, do_close);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
* InsertFakeRequest
|
* InsertFakeRequest
|
||||||
* Splice a consed up (possibly partial) request in as the next request.
|
* Splice a consed up (possibly partial) request in as the next request.
|
||||||
|
|
Loading…
Reference in New Issue