summaryrefslogtreecommitdiff
path: root/appl/spree/man/styxservers.man2
blob: fca2748a87a9fd15342b93ef54772f5ff3328441 (plain)
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
.TH STYXSERVERS 2
.SH NAME
styxservers \-
Styx server implementation assistance
.SH SYNOPSIS
.EX
include "sys.m";
include "styx.m";
Tmsg, Rmsg: import Styx;
include "styxservers.m";
styxservers := load Styxservers Styxservers->PATH;
Styxserver, Fid, Navigator: import styxservers;

Styxserver: adt {
    fd:      ref Sys->FD;     # file server end of connection
    t:       ref Navigator;   # name space navigator for this server
    msize:   int;             # negotiated Styx message size

    new:     fn(fd: ref Sys->FD, t: ref Navigator, rootpath: big)
                  :(chan of ref Tmsg, ref Styxserver);
    reply:   fn(srv: self ref Styxserver, m: ref Rmsg): int;

    # protocol operations
    attach:  fn(srv: self ref Styxserver, m: ref Tmsg.Attach): ref Fid;
    clunk:   fn(srv: self ref Styxserver, m: ref Tmsg.Clunk): ref Fid;
    walk:    fn(srv: self ref Styxserver, m: ref Tmsg.Walk): ref Fid;
    open:    fn(srv: self ref Styxserver, m: ref Tmsg.Open): ref Fid;
    read:    fn(srv: self ref Styxserver, m: ref Tmsg.Read): ref Fid;
    remove:  fn(srv: self ref Styxserver, m: ref Tmsg.Remove): ref Fid;
    stat:    fn(srv: self ref Styxserver, m: ref Tmsg.Stat);
    default: fn(srv: self ref Styxserver, gm: ref Tmsg);

    # check validity
    cancreate: fn(srv: self ref Styxserver, m: ref Tmsg.Create)
                  :(ref Fid, int, ref Sys->Dir, string);
    canopen:   fn(srv: self ref Styxserver, m: ref Tmsg.Open)
		          :(ref Fid, int, ref Sys->Dir, string);
    canread:   fn(srv: self ref Styxserver, m: ref Tmsg.Read)
                  :(ref Fid, string);
    canwrite:  fn(srv: self ref Styxserver, m: ref Tmsg.Write)
                  :(ref Fid, string);

    # fid management
    getfid:  fn(srv: self ref Styxserver, fid: int): ref Fid;
    newfid:  fn(srv: self ref Styxserver, fid: int): ref Fid;
    delfid:  fn(srv: self ref Styxserver, c: ref Fid);
    allfids: fn(srv: self ref Styxserver): list of ref Fid;

    iounit:  fn(srv: self ref Styxserver): int;
};

Fid: adt {
    fid:    int;       # client's fid
    path:   big;       # file's 64-bit unique path
    qtype:  int;       # file's qid type (eg, Sys->QTDIR if directory)
    isopen: int;       # non-zero if file is open
    mode:   int;       # if open, the open mode
    uname:  string;    # user name from original attach
    param:  string;    # attach aname from original attach
    data:   array of byte;   # application data

    clone:  fn(f: self ref Fid, nf: ref Fid): ref Fid;
    open:   fn(f: self ref Fid, mode: int, qid: Sys->Qid);
    walk:   fn(f: self ref Fid, qid: Sys->Qid);
};

Navop: adt {
    reply:  chan of (ref Sys->Dir, string);  # channel for reply
    path:   big;      # file or directory path
    pick {
    Stat =>
    Walk =>
        name: string;
    Readdir =>
        offset: int;  # index (origin 0) of first entry to return
        count:  int;  # number of directory entries requested
    }
};

Navigator: adt {
    new:    fn(c: chan of ref Navop): ref Navigator;
    stat:   fn(t: self ref Navigator, path: big): (ref Sys->Dir, string);
    walk:   fn(t: self ref Navigator, parent: big, name: string)
               : (ref Sys->Dir, string);
    readdir:fn(t: self ref Navigator, path: big,
               offset, count: int): array of ref Sys->Dir;
};

init:      fn(styx: Styx);
traceset:  fn(on: int);

readbytes: fn(m: ref Styx->Tmsg.Read, d: array of byte):
              ref Styx->Rmsg.Read;
readstr:   fn(m: ref Styx->Tmsg.Read, s: string):
              ref Styx->Rmsg.Read;
openok:    fn(uname: string, omode,
              perm: int, funame, fgname: string): int;
openmode:  fn(o: int): int;
.EE
.SH DESCRIPTION
When writing a Styx file server, there are some
commonly performed tasks that are
fiddly or tedious to implement each time.
.B Styxservers
provides a framework to automate some of these
routine tasks.
In particular, it helps manage the fid space,
implements common default processing for protocol messages,
and assists walking around the
directory hierarchy and reading of directories. Other
tasks, such as defining the structure of the
name space, and reading and writing files in it, are
left to the file server program itself.
Familiarity with Section 5 of the manual which defines the protocol
(see
.IR intro (5)),
and with the representation of Styx messages in Limbo
(see
.IR styx (2)),
is a prerequisite for use of this module.
.PP
.B Styxservers
does not define or store any of the directory hierarchy itself;
instead it queries an external process for information
when necessary, through a value of type
.BR Navigator ,
which encapsulates communication with that process.
That process must be started up
independently of each
.BR Styxserver ;
a channel to such a process should be provided
when starting a new
.BR Styxserver .
The channel carries messages of type
.BR Navop .
.IR Styxservers-nametree (2)
provides a ready-made
implementation of such a process that is sufficient for many applications.
.PP
.B Styxserver
keeps tabs on the fids that are currently in use, and remembers
some associated information, such as the Qid path
of the file, whether it has been opened, etc.
It does this using values of type
.BR Fid .
.PP
Once the
.B Styxservers
module has been loaded,
the
.B init
function must be called before anything else,
to initialise its internal state. The
.I styx
argument should be an implementation of
the
.IR styx (2)
module, which will be used to translate messages.
Individual
.B Styxserver
instances do not share state, and are therefore
independently thread-safe.
.SS Fid representation
.B Styxservers
represents each active fid as a
.B Fid
value,
which has the following public members:
.TF param
.TP
.B fid
The integer
.I fid
value provided by the client to refer to an active instance of a file in the file server,
as described in
.IR intro (5).
.TP
.B path
The 64-bit qid path that uniquely identifies the file on the file server,
as described in
.IR intro (5).
It is set by
.IB f .walk
and
.IB f .open
(see below).
.TP
.B qtype
The file's qid type; it is
.B Sys->QTDIR
if and only if the fid refers to a directory.
The value is set by
.IB f .walk
and
.IB f .open
(see below).
.TP
.B isopen
Non-zero if and only if the fid has been opened by an
.IR open (5)
message.
It is initially zero, and set by
.IB f .open
(see below).
.TP
.B mode
Valid only if the fid has been opened.
It has one of the values
.BR Sys->OREAD ,
.BR Sys->OWRITE ,
.BR Sys->ORDWR ,
possibly ORed with
.BR Sys->ORCLOSE ,
corresponding to the mode with which the file was opened.
It is set by
.IB f .open
(see below).
.TP
.B uname
The name of the user that created the fid.
.TP
.B param
Set by
.B Styxservers
to the
.B aname
of the initial
.IR attach (5)
message,
and subsequently inherited by each new fid created by
.IR walk (5),
but not otherwise used by
.B Styxservers
itself, and may be changed by the application.
.TP
.B data
Unused by
.BR Styxservers ;
for application use.
It might be used, for instance, to implement a file that gives different
data to different clients.
.TP
.IB f .clone( nf )
Copy the current state of all members of
.I f
except
.IB f .fid\f1,\fP
into
.IR nf ,
and return
.IR nf .
Used by
.BR Styxserver.walk ,
and is needed by an application only if it replaces that function.
.TP
.IB f .walk( qid )
Make
.I f
refer to the file with the given
.IR qid :
set
.IB f .path
and
.IB f .qtype
from
.IB qid .path
and
.IB qid .qtype .
Used by
.IB Styxserver.walk
and is needed by an application only if it replaces that function.
.TP
.IB f .open( mode,\ qid )
Mark
.I f
as `open',
set
.IR f .mode
to
.IR mode ,
and set
.B path
and
.B qtype
to the path and type of
.IR qid .
Used by the
implementations of
.B open
and
.B create
messages.
The default implementation of
.IR open (5)
in
.B Styxserver
obtains the value of
.I mode
from
.B Styxserver.canopen
(below),
and
obtains the value of
.I qid
by querying the application's navigator.
.SS Styxserver and file server state
Each
.B Styxserver
value holds the state for a single file server, including its active fids,
the link to the external name space process, and other internal data.
Most of the state is manipulated through the member functions described below.
The exceptions are two read-only values:
the
.B Navigator
reference
.IB srv .t
which can be used to access that navigator; and
the file descriptor
.IB srv .fd
that is the file server's end of the connection to the Styx client.
Both values are initially provided by the file serving application,
but can be accessed through the
.B Styxserver
value for convenience.
The file descriptor value is normally used only through
.BR Styxserver.reply ,
but will be needed directly if the caller needs the file descriptor value
as a parameter to
.IR sys-pctl (2)
when insulating the serving process's file descriptors from the surrounding environment.
.PP
The first set of functions in
.B Styxserver
provides common and default actions:
.TP
.B Styxserver.new(\fIfd\fP,\ \fIt\fP,\ \fIrootpath\fP)
Create a new
.BR Styxserver .
It returns a tuple, say
.RI ( c ", " srv ),
and spawns a new process, which uses
.IR styx (2)
to read and parse Styx messages read
from
.IR fd ,
and send them down
.IR c ;
.I t
should be a
.B Navigator
adt which the
.B Styxserver
can use to answer queries
on the name space (see ``Navigating file trees'', below).
.I Rootpath
gives the Qid path of the root of the served name space.
.TP
.IB srv .reply(\fIm\fP)
Send a reply (R-message) to a client. The various utility methods,
listed below, call this function to make their response.
.TP
.IB srv .attach(\fIm\fP)
Respond to an
.IR attach (5)
message
.IR m ,
creating a new fid in the process, and returning it.
Returns
.B nil
if
.IB m .fid
is a duplicate of an existing fid.
The value of the attach parameter
.IB m .aname
is copied into the new fid's
.B param
field, as is the attaching user name,
.IB m .uname .
.TP
.IB srv .clunk(\fIm\fP)
Respond to a
.IR clunk (5)
message
.IR m ,
and return the old
.BR Fid .
Note that this does nothing about remove-on-close
files; that should be programmed explicitly if needed.
.TP
.IB srv .walk(\fIm\fP)
Respond to a
.IR walk (5)
message
.IR m ,
querying
.IB srv . t
for information on existing files.
.TP
.IB srv .open(\fIm\fP)
Respond to an
.IR open (5)
message
.IR m .
This will allow a file to be opened if its permissions allow the
specified mode of access.
.TP
.IB srv .read(\fIm\fP)
Respond to a
.IR read (5)
message
.IR m .
If a directory is being read, the appropriate reply
is made; for files, an error is given.
.TP
.IB srv .remove(\fIm\fP)
Respond to a
.IR remove (5)
message
.IR m
with an error, clunking the fid as it does so,
and returning the old
.BR Fid .
.TP
.IB srv .stat(\fIm\fP)
Respond to a
.IR stat (5)
message
.IR m .
.TP
.IB srv .default(\fIgm\fP)
Respond to an arbitrary T-message,
.IR gm ,
as appropriate (eg, by calling
.IB srv .walk
for a
.IR walk (5)
message).
It responds appropriately to
.IR version (5),
and replies to
.B Tauth
(see
.IR attach (5))
stating that authentication is not required.
Other messages without an associated
.B Styxserver
function are generally responded to
with a ``permission denied'' error.
.PP
All the functions above check the validity of the fids, modes, counts and offsets
in the messages, and automatically reply to the client with a suitable
.IR error (5)
message on error.
.PP
The following further
.B Styxserver
operations are useful
in applications that override all or part of the default handling
(in particular,
to process read and write requests):
.TP
.IB srv .canopen( m )
Check whether it is legal to open a file as requested by message
.IR m :
the fid is valid but not already open, the corresponding file exists and its
permissions allow access in the requested mode, and if
.B Sys->ORCLOSE
is requested, the parent directory is writable (to allow the file to be removed when closed).
.B Canopen
returns a tuple, say
.RI ( f ,\  mode ,\  d,\ err\ \fP).
If the open request was invalid,
.I f
will be nil, and the string
.I err
will diagnose the error (for return to the client in an
.B Rmsg.Error
message).
If the request was valid:
.I f
contains the
.B Fid
representing the file to be opened;
.I mode
is the access mode derived from
.IB m .mode ,
.BR Sys->OREAD ,
.BR Sys->OWRITE ,
.BR Sys->ORDWR ,
ORed with
.BR Sys->ORCLOSE ;
.I d
is a
.B Dir
value giving the file's attributes, obtained from the navigator;
and
.I err
is nil.
Once the application has done what it must to open the file,
it must call
.IB f .open
to mark it open.
.TP
.IB srv .cancreate( m )
Checks whether the
creation of the file requested by
message
.I m
is legal:
the fid is valid but not open, refers to a directory,
the permissions returned by
.IR srv .t.stat
show that directory is writable by the requesting user,
the name does not already exist in that directory,
and the mode with which the new file would be opened is valid.
.B Cancreate
returns a tuple, say
.RI ( f ,\  mode,\  d,\ err\ \fP).
If the creation request was invalid,
.I f
will be nil, and the string
.I err
will diagnose the error, for use in an error reply to the client.
If the request was valid:
.I f
contains the
.B Fid
representing the parent directory;
.I mode
is the open mode as defined for
.B canopen
above;
.I d
is a
.B Dir
value containing some initial attributes for the new file or directory;
and
.I err
is nil.
The initial attributes set in
.I d
are:
.IB d .name
(the name of the file to be created);
.IB d .uid
and
.IB d .muid
(the user that did the initial attach);
.IB d .gid ,
.IB d .dtype ,
.IB d .dev
(taken from the parent directory's attributes);
and
.IB d .mode
holds the file mode that should be attributed to the new
file (taking into account the parent mode, as
described in
.IR open (5)).
The caller must supply
.IB d .qid
once the file has successfully been created,
and
.IB d .atime
and
.IB d .mtime ;
it must also call
.IB f .open
to mark
.I f
open and set its path to the file's path.
If the file cannot be created successfully, the application should reply with
an
.IR error (5)
message and leave
.I f
untouched.
The
.B Fid
.I f
will then continue to refer to the original directory, and remain unopened.
.TP
.IB srv .canread( m )
Checks whether
.IR read (5)
message
.I m
refers to a valid fid that has been opened for reading,
and that the count and file offset are non-negative.
.B Canread
returns a tuple, say
.RI ( f ,\  err );
if the attempted access is illegal,
.I f
will be nil, and
.I err
contains a description of the error,
otherwise
.I f
contains the
.B Fid
corresponding to the file in question.
It is typically called by an application's implementation of
.B Tmsg.Read
to obtain the
.B Fid
corresponding to the fid in the message, and check the access.
.TP
.IB srv .canwrite( m )
Checks whether
message
.I m
refers to a valid fid that has been opened for writing,
and that the file offset is non-negative.
.B Canwrite
returns a tuple, say
.RI ( f ,\  err );
if the attempted access is illegal,
.I f
will be nil, and
.I err
contains a description of the error,
otherwise
.I f
contains the
.B Fid
corresponding to the file in question.
It is typically called by an application's implementation of
.B Tmsg.Write
to obtain the
.B Fid
corresponding to the fid in the message, and check the access.
.TP
.IB srv .iounit()
Return an appropriate value for use as the
.I iounit
element in
.B Rmsg.Open
and
.B Rmsg.Create
replies,
as defined in
.IR open (5),
based on the message size negotiated by the initial
.IR version (5)
message.
.PP
The remaining functions are normally used only by servers that need to
override default actions.
They maintain and access the mapping between a client's fid values presented in
.B Tmsg
messages and the
.B Fid
values that represent the corresponding files internally.
.TP
.IB srv .newfid(\fIfid\fP)
Create a new
.B Fid
associated with number
.I fid
and return it.
Return nil if the
.I fid
is already in use (implies a client error if the server correctly clunks fids).
.TP
.IB srv .getfid(\fIfid\fP)
Get the
.B Fid
data associated with numeric id
.IR fid ;
return nil if there is none such (a malicious or erroneous client
can cause this).
.TP
.IB srv .delfid(\fIfid\fP)
Delete
.I fid
from the table of fids in the
.BR Styxserver .
(There is no error return.)
.TP
.IB srv .allfids()
Return a list of all current fids (ie, the files currently active on the client).
.PP
.B Newfid
is required when processing
.IR auth (5),
.IR attach (5)
and
.IR walk (5)
messages to create new fids.
.B Delfid
is used to clunk fids when processing
.IR clunk (5),
.IR remove (5),
and in a failed
.IR walk (5)
when it specified a new fid.
All other messages should refer only to already existing fids, and the associated
.B Fid
data is fetched by
.BR getfid .
.SS Navigating file trees
When a
.B Styxserver
instance needs to know about the namespace,
it queries an external process through a channel
by sending a
.B Navop
request;
each such request carries with it a
.B reply
channel through which the
reply should be made.
The reply tuple has a reference to a
.B Sys->Dir
value that is non-nil on success, and a diagnostic string
that is non-nil on error.
.PP
Files in the tree are referred to
by their Qid
.BR path .
The requests are:
.TF Walk
.TP
.BR Stat
.br
Find a file in the hierarchy by its
.BR path ,
and reply with the corresponding
.B Dir
data if found (or a diagnostic on error).
.TP
.BR Walk
.br
Look for file
.B name
in the directory with the given
.BR path .
.TP
.BR Readdir
.br
Get information on selected files in the directory with the given
.BR path .
In this case, the reply channel is used to send
a sequence of values, one for each entry in the directory, finishing with a tuple value
.BR (nil,nil) .
The entries to return are those selected by an
.B offset
that is the index (origin 0) of the first directory entry to return,
and a
.B count
of a number of entries to return starting with that index.
Note that both values are expressed in units of directory entries, not as byte counts.
.PP
.B Styxserver
provides a
.B Navigator
adt to enable convenient access to this functionality; calls
into the
.B Navigator
adt are bundled up into requests on the channel, and the
reply returned.
The functions provided are:
.TP 10
.BI Navigator.new( c )
Create a new
.BR Navigator ,
sending requests down
.IR c .
.TP
.IB t .stat(\fIpath\fP)
Find the file with the given
.IR path .
Return a tuple
.RI ( d ,\  err ),
where
.I d
holds directory information for the file
if found; otherwise
.I err
contains an error message.
.TP
.IB t .walk(\fIparent\fP,\ \fIname\fP)
Find the file with name
.I name
inside parent directory
.IR parent .
Return a tuple as for
.BR stat .
.TP
.IB t .readdir(\fIpath\fP,\ \fIoffset\fP,\ \fIcount\fP)
Return directory data read from directory
.IR path ,
starting at entry
.I offset
for
.I count
entries.
.SS Other functions
The following functions provide some commonly used functionality:
.TP 10
.BI readbytes( m ,\  d )
Assuming that the file in question contains data
.IR d ,
.B readbytes
returns an appropriate reply to
.IR read (5)
message
.IR m ,
taking account of
.IB m .offset
and
.IB m.count
when extracting data from
.IR d .
.TP 10
.BI readstr( m ,\  s )
Assuming that the file in question contains string
.IR s ,
.B readstr
returns an appropriate reply to
.IR read (5)
message
.IR m ,
taking account of
.IB m .offset
and
.IB m.count
when extracting data from the UTF-8 representation of
.IR s .
.TP
.BI openok (\fIuname\fP,\ \fIomode\fP,\ \fIperm\fP,\ \fIfuid\fP,\ \fIfgid\fP)
Does standard permission checking, assuming user
.I uname
is trying to open a file with access mode
.IR omode ,
where the file is owned by
.IR fuid ,
has group
.IR fgid ,
and permissions
.IR perm .
Returns true (non-zero) if permission would be granted, and false (zero) otherwise.
.TP
.BI openmode( o )
Checks to see whether the open mode
.I o
is well-formed; if it is not,
.B openmode
returns -1; if it is, it returns the mode
with OTRUNC and ORCLOSE flags removed.
.TP
.BI traceset( on )
If
.I on
is true (non-zero),
will trace Styx requests and replies, on standard error.
This option must be set before creating a
.BR Styxserver ,
to ensure that it preserves its standard error descriptor.
.SS Constants
.B Styxservers
defines a number of constants applicable to the writing
of Styx servers, including:
.TP
.BR Einuse\fP,\fP\ Ebadfid\fP,\fP\ Eopen\fP,\fP\ Enotfound\fP,\fP\ Enotdir\fP,\fP\ Eperm\fP,\fP\ Ebadarg\fP,\fP\ Eexists
These provide standard strings for commonly used error conditions,
to be used in
.B Rmsg.Error
replies.
.SS Authentication
If authentication is required beyond that provided at the link level
(for instance by
.IR security-auth (2)),
the server application must handle
.B Tauth
itself,
remember the value of
.I afid
in that message, and generate an
.B Rauth
reply with a suitable Qid referring to a file with
.B Qid.qtype
of
.BR QTAUTH .
Following successful authentication by read and write on that file,
it must associate that status with the
.IR afid .
Then, on a subsequent
.B Tattach
message, before calling
.I srv .attach
it must check that the
.BR Tattach 's
.I afid
value corresponds to one previously authenticated, and
reply with an appropriate error if not.
.SH SOURCE
.B /appl/lib/styxservers.b
.SH SEE ALSO
.IR styxservers-nametree (2),
.IR sys-stat (2),
.IR intro (5)