libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

message.c (5917B)


      1 /* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #include <stdlib.h>
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include "ixp_local.h"
      8 
      9 enum {
     10 	SByte = 1,
     11 	SWord = 2,
     12 	SDWord = 4,
     13 	SQWord = 8,
     14 };
     15 
     16 #define SString(s) (SWord + strlen(s))
     17 enum {
     18 	SQid = SByte + SDWord + SQWord,
     19 };
     20 
     21 /**
     22  * Type: IxpMsg
     23  * Type: IxpMsgMode
     24  * Function: ixp_message
     25  *
     26  * The IxpMsg struct represents a binary message, and is used
     27  * extensively by libixp for converting messages to and from
     28  * wire format. The location and size of a buffer are stored in
     29  * P<data> and P<size>, respectively. P<pos> points to the
     30  * location in the message currently being packed or unpacked,
     31  * while P<end> points to the end of the message. The packing
     32  * functions advance P<pos> as they go, always ensuring that
     33  * they don't read or write past P<end>.  When a message is
     34  * entirely packed or unpacked, P<pos> whould be less than or
     35  * equal to P<end>. Any other state indicates error.
     36  *
     37  * ixp_message is a convenience function to pack a construct an
     38  * IxpMsg from a buffer of a given P<length> and a given
     39  * P<mode>. P<pos> and P<data> are set to P<data> and P<end> is
     40  * set to P<data> + P<length>.
     41  *
     42  * See also:
     43  *	F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, F<ixp_pu64>,
     44  *	F<ixp_pstring>, F<ixp_pstrings>
     45  */
     46 IxpMsg
     47 ixp_message(char *data, uint length, uint mode) {
     48 	IxpMsg m;
     49 
     50 	m.data = data;
     51 	m.pos = data;
     52 	m.end = data + length;
     53 	m.size = length;
     54 	m.mode = mode;
     55 	return m;
     56 }
     57 
     58 /**
     59  * Function: ixp_freestat
     60  * Function: ixp_freefcall
     61  *
     62  * These functions free malloc(3) allocated data in the members
     63  * of the passed structures and set those members to nil. They
     64  * do not free the structures themselves.
     65  *
     66  * See also:
     67  *	S<IxpFcall>, S<IxpStat>
     68  */
     69 void
     70 ixp_freestat(IxpStat *s) {
     71 	free(s->name);
     72 	free(s->uid);
     73 	free(s->gid);
     74 	free(s->muid);
     75 	s->name = s->uid = s->gid = s->muid = nil;
     76 }
     77 
     78 void
     79 ixp_freefcall(IxpFcall *fcall) {
     80 	switch(fcall->hdr.type) {
     81 	case RStat:
     82 		free(fcall->rstat.stat);
     83 		fcall->rstat.stat = nil;
     84 		break;
     85 	case RRead:
     86 		free(fcall->rread.data);
     87 		fcall->rread.data = nil;
     88 		break;
     89 	case RVersion:
     90 		free(fcall->version.version);
     91 		fcall->version.version = nil;
     92 		break;
     93 	case RError:
     94 		free(fcall->error.ename);
     95 		fcall->error.ename = nil;
     96 		break;
     97 	}
     98 }
     99 
    100 uint16_t
    101 ixp_sizeof_stat(IxpStat *stat) {
    102 	return SWord /* size */
    103 		+ SWord /* type */
    104 		+ SDWord /* dev */
    105 		+ SQid /* qid */
    106 		+ 3 * SDWord /* mode, atime, mtime */
    107 		+ SQWord /* length */
    108 		+ SString(stat->name)
    109 		+ SString(stat->uid)
    110 		+ SString(stat->gid)
    111 		+ SString(stat->muid);
    112 }
    113 
    114 void
    115 ixp_pfcall(IxpMsg *msg, IxpFcall *fcall) {
    116 	ixp_pu8(msg, &fcall->hdr.type);
    117 	ixp_pu16(msg, &fcall->hdr.tag);
    118 
    119 	switch (fcall->hdr.type) {
    120 	case TVersion:
    121 	case RVersion:
    122 		ixp_pu32(msg, &fcall->version.msize);
    123 		ixp_pstring(msg, &fcall->version.version);
    124 		break;
    125 	case TAuth:
    126 		ixp_pu32(msg, &fcall->tauth.afid);
    127 		ixp_pstring(msg, &fcall->tauth.uname);
    128 		ixp_pstring(msg, &fcall->tauth.aname);
    129 		break;
    130 	case RAuth:
    131 		ixp_pqid(msg, &fcall->rauth.aqid);
    132 		break;
    133 	case RAttach:
    134 		ixp_pqid(msg, &fcall->rattach.qid);
    135 		break;
    136 	case TAttach:
    137 		ixp_pu32(msg, &fcall->hdr.fid);
    138 		ixp_pu32(msg, &fcall->tattach.afid);
    139 		ixp_pstring(msg, &fcall->tattach.uname);
    140 		ixp_pstring(msg, &fcall->tattach.aname);
    141 		break;
    142 	case RError:
    143 		ixp_pstring(msg, &fcall->error.ename);
    144 		break;
    145 	case TFlush:
    146 		ixp_pu16(msg, &fcall->tflush.oldtag);
    147 		break;
    148 	case TWalk:
    149 		ixp_pu32(msg, &fcall->hdr.fid);
    150 		ixp_pu32(msg, &fcall->twalk.newfid);
    151 		ixp_pstrings(msg, &fcall->twalk.nwname, fcall->twalk.wname, nelem(fcall->twalk.wname));
    152 		break;
    153 	case RWalk:
    154 		ixp_pqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid, nelem(fcall->rwalk.wqid));
    155 		break;
    156 	case TOpen:
    157 		ixp_pu32(msg, &fcall->hdr.fid);
    158 		ixp_pu8(msg, &fcall->topen.mode);
    159 		break;
    160 	case ROpen:
    161 	case RCreate:
    162 		ixp_pqid(msg, &fcall->ropen.qid);
    163 		ixp_pu32(msg, &fcall->ropen.iounit);
    164 		break;
    165 	case TCreate:
    166 		ixp_pu32(msg, &fcall->hdr.fid);
    167 		ixp_pstring(msg, &fcall->tcreate.name);
    168 		ixp_pu32(msg, &fcall->tcreate.perm);
    169 		ixp_pu8(msg, &fcall->tcreate.mode);
    170 		break;
    171 	case TRead:
    172 		ixp_pu32(msg, &fcall->hdr.fid);
    173 		ixp_pu64(msg, &fcall->tread.offset);
    174 		ixp_pu32(msg, &fcall->tread.count);
    175 		break;
    176 	case RRead:
    177 		ixp_pu32(msg, &fcall->rread.count);
    178 		ixp_pdata(msg, &fcall->rread.data, fcall->rread.count);
    179 		break;
    180 	case TWrite:
    181 		ixp_pu32(msg, &fcall->hdr.fid);
    182 		ixp_pu64(msg, &fcall->twrite.offset);
    183 		ixp_pu32(msg, &fcall->twrite.count);
    184 		ixp_pdata(msg, &fcall->twrite.data, fcall->twrite.count);
    185 		break;
    186 	case RWrite:
    187 		ixp_pu32(msg, &fcall->rwrite.count);
    188 		break;
    189 	case TClunk:
    190 	case TRemove:
    191 	case TStat:
    192 		ixp_pu32(msg, &fcall->hdr.fid);
    193 		break;
    194 	case RStat:
    195 		ixp_pu16(msg, &fcall->rstat.nstat);
    196 		ixp_pdata(msg, (char**)&fcall->rstat.stat, fcall->rstat.nstat);
    197 		break;
    198 	case TWStat: {
    199 		uint16_t size;
    200 		ixp_pu32(msg, &fcall->hdr.fid);
    201 		ixp_pu16(msg, &size);
    202 		ixp_pstat(msg, &fcall->twstat.stat);
    203 		break;
    204 		}
    205 	}
    206 }
    207 
    208 /**
    209  * Function: ixp_fcall2msg
    210  * Function: ixp_msg2fcall
    211  *
    212  * These functions pack or unpack a 9P protocol message. The
    213  * message is set to the appropriate mode and its position is
    214  * set to the begining of its buffer.
    215  *
    216  * Returns:
    217  *	These functions return the size of the message on
    218  *	success and 0 on failure.
    219  * See also:
    220  *	F<IxpMsg>, F<ixp_pfcall>
    221  */
    222 uint
    223 ixp_fcall2msg(IxpMsg *msg, IxpFcall *fcall) {
    224 	uint32_t size;
    225 
    226 	msg->end = msg->data + msg->size;
    227 	msg->pos = msg->data + SDWord;
    228 	msg->mode = MsgPack;
    229 	ixp_pfcall(msg, fcall);
    230 
    231 	if(msg->pos > msg->end)
    232 		return 0;
    233 
    234 	msg->end = msg->pos;
    235 	size = msg->end - msg->data;
    236 
    237 	msg->pos = msg->data;
    238 	ixp_pu32(msg, &size);
    239 
    240 	msg->pos = msg->data;
    241 	return size;
    242 }
    243 
    244 uint
    245 ixp_msg2fcall(IxpMsg *msg, IxpFcall *fcall) {
    246 	msg->pos = msg->data + SDWord;
    247 	msg->mode = MsgUnpack;
    248 	ixp_pfcall(msg, fcall);
    249 
    250 	if(msg->pos > msg->end)
    251 		return 0;
    252 
    253 	return msg->pos - msg->data;
    254 }
    255