+NEWS for lufs-0.9.7captive8
[lufs.git] / lufsd / message.c
1 /*
2  * message.c
3  * Copyright (C) 2002 Florin Malita <mali@go.ro>
4  *
5  * This file is part of LUFS, a free userspace filesystem implementation.
6  * See http://lufs.sourceforge.net/ for updates.
7  *
8  * LUFS is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * LUFS is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <unistd.h>
24 #include <string.h>
25 #include <time.h>
26 #include <errno.h>
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30
31 #include <lufs/proto.h>
32 #include <lufs/fs.h>
33
34 #include "message.h"
35
36 int
37 lu_check_to(int rd_fd, int wr_fd, int time_out){
38     fd_set rd, wr;
39     int res, maxfd = 0;
40     struct timeval tv;
41
42     FD_ZERO(&rd);
43     FD_ZERO(&wr);
44
45     if(rd_fd){
46         FD_SET(rd_fd, &rd);
47         maxfd = rd_fd > maxfd ? rd_fd : maxfd;
48     }
49
50     if(wr_fd){
51         FD_SET(wr_fd, &wr);
52         maxfd = wr_fd > maxfd ? wr_fd : maxfd;
53     }
54
55     tv.tv_sec = time_out;
56     tv.tv_usec = 0;
57
58     do{
59         res = select(maxfd + 1, &rd, &wr, NULL, &tv);
60
61     }while((res < 0) && (errno == EINTR));    
62
63     if(res > 0)
64         return 0;
65
66     if(res < 0){
67             WARN("select call failed: %s", strerror(errno));
68             return -errno;
69     }
70        
71     WARN("operation timed out!");
72
73     return -ETIMEDOUT;
74 }
75
76 int
77 lu_atomic_read(int fd, char *buf, int len, int time_out){
78     int res, offset = 0;
79
80     do{
81         if((time_out) && ((res = lu_check_to(fd, 0, time_out)) < 0))
82             return res;
83
84         do{
85             res = read(fd, buf + offset, len - offset);
86         }while((res < 0) && (errno == EINTR));
87
88         if(res <= 0){
89             WARN("read call failed: %s", strerror(errno));
90             return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE);
91         }
92
93         offset += res;
94
95     }while(offset < len);
96
97     return offset;
98 }
99
100 int
101 lu_atomic_write(int fd, char *buf, int len, int time_out){
102     int res, offset = 0;
103
104     do{
105         if((time_out) && ((res = lu_check_to(0, fd, time_out)) < 0))
106             return res;
107
108         do{
109             res = write(fd, buf + offset, len - offset);
110         }while((res < 0) && (errno == EINTR));
111
112         if(res <= 0){
113             WARN("write call failed: %s", strerror(errno));
114             return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE);
115         }
116
117         offset += res;
118
119     }while(offset < len);
120
121     return offset;
122 }
123
124 struct message*
125 lu_recvmsg(struct message *msg, int sock){
126
127     msg->m_data = msg->m_buffer;
128
129     if(lu_atomic_read(sock, (char*)&msg->m_hdr, sizeof(struct lu_msg), 0) < 0){
130         WARN("recv failed");
131         return NULL;
132     }
133
134     if(msg->m_hdr.msg_datalen){
135         if(msg->m_hdr.msg_datalen > MAX_DATA){
136             ERROR("message too long: %u bytes", msg->m_hdr.msg_datalen);
137             return NULL;
138         }
139         
140         if(lu_atomic_read(sock, msg->m_data, msg->m_hdr.msg_datalen, 0) < 0){
141             WARN("recv failed");
142             return NULL;
143         }
144     }
145
146     return msg;
147 }
148
149 int
150 lu_sendmsg(struct message *msg, int sock){
151
152     if(lu_atomic_write(sock, (char*)&msg->m_hdr, sizeof(struct lu_msg), 0) < 0){
153         WARN("send failed");
154         return -1;
155     }
156
157     if((msg->m_hdr.msg_datalen) && (lu_atomic_write(sock, msg->m_data, msg->m_hdr.msg_datalen, 0) < 0)){
158         WARN("send failed");
159         return -1;
160     }
161     
162     return 0;
163 }
164
165 struct message*
166 lu_makemsg(struct message *msg, unsigned short type, char *data, unsigned short len){
167     
168     msg->m_hdr.msg_type = type;
169     msg->m_hdr.msg_version = PVERSION;
170     msg->m_hdr.msg_datalen = len;
171     msg->m_hdr.msg_pid = getpid();
172     
173     if(data)
174         msg->m_data = data;
175     else
176         msg->m_data = msg->m_buffer;
177
178     return msg;
179 }
180