Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/cs/cat.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* Glenn Fowler
24
* AT&T Bell Laboratories
25
*
26
* file cat service
27
* this gets around NonFS multi-client file cache inconsistencies
28
*/
29
30
static const char id[] = "\n@(#)$Id: cs.cat (AT&T Bell Laboratories) 1995-05-09 $\0\n";
31
32
#include <ast.h>
33
#include <cs.h>
34
#include <error.h>
35
#include <hash.h>
36
#include <msg.h>
37
38
#define CAT_MSG (1<<0) /* cs msg with size */
39
40
typedef struct /* open file id key */
41
{
42
unsigned long dev; /* st_dev */
43
unsigned long ino; /* st_ino */
44
} Fid_t;
45
46
typedef struct /* open file info */
47
{
48
HASH_HEADER;
49
int fd; /* O_APPEND fd */
50
int flags; /* CAT_* flags */
51
int reference; /* user reference count */
52
} File_t;
53
54
typedef struct /* server state */
55
{
56
Hash_table_t* files; /* Fid_t hash */
57
int active; /* # open connections */
58
int dormant; /* dormant timeout check */
59
char buf[MSG_SIZE_BUF];/* io buffer */
60
File_t* cat[1]; /* user file reference */
61
} State_t;
62
63
/*
64
* initialize the state
65
*/
66
67
static void*
68
svc_init(void* handle, int fdmax)
69
{
70
State_t* state;
71
72
NoP(handle);
73
if (!(state = newof(0, State_t, 1, (fdmax - 1) * sizeof(File_t*))))
74
error(3, "out of space [state]");
75
if (!(state->files = hashalloc(NiL, HASH_set, HASH_ALLOCATE, HASH_namesize, sizeof(Fid_t), HASH_name, "files", 0)))
76
error(3, "out of space [files]");
77
cstimeout(CS_SVC_DORMANT * 1000L);
78
return((void*)state);
79
}
80
81
/*
82
* add a new connection
83
*/
84
85
static int
86
svc_connect(void* handle, int fd, Cs_id_t* id, int clone, char** argv)
87
{
88
register State_t* state = (State_t*)handle;
89
register File_t* fp;
90
register char* s;
91
int ad;
92
int flags = 0;
93
Fid_t fid;
94
struct stat st;
95
96
NoP(id);
97
NoP(clone);
98
if (!argv)
99
return(-1);
100
while ((s = *argv++) && *s != '/')
101
switch (*s)
102
{
103
case 'm':
104
flags |= CAT_MSG;
105
break;
106
}
107
if (!s || (ad = csopen(s, 0)) < 0 && (ad = open(s, O_CREAT|O_APPEND|O_WRONLY|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
108
return(-1);
109
if (fstat(ad, &st))
110
{
111
close(ad);
112
return(-1);
113
}
114
fid.dev = st.st_dev;
115
fid.ino = st.st_ino;
116
if (!(fp = (File_t*)hashlook(state->files, (char*)&fid, HASH_CREATE|HASH_SIZE(sizeof(File_t)), NiL)))
117
{
118
close(ad);
119
return(-1);
120
}
121
if (!fp->reference++) fp->fd = ad;
122
else close(ad);
123
fp->flags |= flags;
124
state->cat[fd] = fp;
125
state->active++;
126
state->dormant = 0;
127
return(0);
128
}
129
130
/*
131
* service a request
132
*/
133
134
static int
135
svc_read(void* handle, int fd)
136
{
137
register State_t* state = (State_t*)handle;
138
register ssize_t n;
139
register ssize_t m;
140
register ssize_t i;
141
register File_t* fp = state->cat[fd];
142
int ok;
143
144
if (fp->flags & CAT_MSG)
145
{
146
if (cspeek(fd, state->buf, MSG_SIZE_SIZE) == MSG_SIZE_SIZE)
147
{
148
ok = 1;
149
if ((m = msggetsize(state->buf)) > MSG_SIZE_SIZE) do
150
{
151
i = (m > sizeof(state->buf)) ? sizeof(state->buf) : m;
152
if ((n = csread(fd, state->buf, i, CS_EXACT)) <= 0)
153
{
154
ok = 0;
155
memzero(state->buf, n = i);
156
}
157
if (cswrite(fp->fd, state->buf, n) != n)
158
{
159
ok = 0;
160
break;
161
}
162
} while ((m -= n) > 0);
163
if (ok) return(0);
164
}
165
}
166
else if ((n = csread(fd, state->buf, sizeof(state->buf), CS_LIMIT)) > 0 && cswrite(fp->fd, state->buf, n) == n)
167
return(0);
168
if (!--fp->reference)
169
{
170
close(fp->fd);
171
hashlook(state->files, fp->name, HASH_DELETE, NiL);
172
}
173
state->active--;
174
return(-1);
175
}
176
177
/*
178
* exit if no open connections on timeout
179
*/
180
181
static int
182
svc_timeout(void* handle)
183
{
184
State_t* state = (State_t*)handle;
185
186
if (!state->active)
187
{
188
if (state->dormant)
189
exit(0);
190
state->dormant = 1;
191
}
192
return(0);
193
}
194
195
int
196
main(int argc, char** argv)
197
{
198
NoP(argc);
199
csserve(NiL, argv[1], svc_init, NiL, svc_connect, svc_read, NiL, svc_timeout);
200
exit(1);
201
}
202
203