The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/devsrv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "../port/error.h"
    7 
    8 
    9 typedef struct Srv Srv;
   10 struct Srv
   11 {
   12         char    *name;
   13         char    *owner;
   14         ulong   perm;
   15         Chan    *chan;
   16         Srv     *link;
   17         ulong   path;
   18 };
   19 
   20 static QLock    srvlk;
   21 static Srv      *srv;
   22 static int      qidpath;
   23 
   24 static int
   25 srvgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
   26 {
   27         Srv *sp;
   28         Qid q;
   29 
   30         if(s == DEVDOTDOT){
   31                 devdir(c, c->qid, "#s", 0, eve, 0555, dp);
   32                 return 1;
   33         }
   34 
   35         qlock(&srvlk);
   36         for(sp = srv; sp && s; sp = sp->link)
   37                 s--;
   38 
   39         if(sp == 0) {
   40                 qunlock(&srvlk);
   41                 return -1;
   42         }
   43 
   44         mkqid(&q, sp->path, 0, QTFILE);
   45         /* make sure name string continues to exist after we release lock */
   46         kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
   47         devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp);
   48         qunlock(&srvlk);
   49         return 1;
   50 }
   51 
   52 static void
   53 srvinit(void)
   54 {
   55         qidpath = 1;
   56 }
   57 
   58 static Chan*
   59 srvattach(char *spec)
   60 {
   61         return devattach('s', spec);
   62 }
   63 
   64 static Walkqid*
   65 srvwalk(Chan *c, Chan *nc, char **name, int nname)
   66 {
   67         return devwalk(c, nc, name, nname, 0, 0, srvgen);
   68 }
   69 
   70 static Srv*
   71 srvlookup(char *name, ulong qidpath)
   72 {
   73         Srv *sp;
   74         for(sp = srv; sp; sp = sp->link)
   75                 if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
   76                         return sp;
   77         return nil;
   78 }
   79 
   80 static int
   81 srvstat(Chan *c, uchar *db, int n)
   82 {
   83         return devstat(c, db, n, 0, 0, srvgen);
   84 }
   85 
   86 char*
   87 srvname(Chan *c)
   88 {
   89         Srv *sp;
   90         char *s;
   91 
   92         for(sp = srv; sp; sp = sp->link)
   93                 if(sp->chan == c){
   94                         s = smalloc(3+strlen(sp->name)+1);
   95                         sprint(s, "#s/%s", sp->name);
   96                         return s;
   97                 }
   98         return nil;
   99 }
  100 
  101 static Chan*
  102 srvopen(Chan *c, int omode)
  103 {
  104         Srv *sp;
  105 
  106         if(c->qid.type == QTDIR){
  107                 if(omode & ORCLOSE)
  108                         error(Eperm);
  109                 if(omode != OREAD)
  110                         error(Eisdir);
  111                 c->mode = omode;
  112                 c->flag |= COPEN;
  113                 c->offset = 0;
  114                 return c;
  115         }
  116         qlock(&srvlk);
  117         if(waserror()){
  118                 qunlock(&srvlk);
  119                 nexterror();
  120         }
  121 
  122         sp = srvlookup(nil, c->qid.path);
  123         if(sp == 0 || sp->chan == 0)
  124                 error(Eshutdown);
  125 
  126         if(omode&OTRUNC)
  127                 error("srv file already exists");
  128         if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR)
  129                 error(Eperm);
  130         devpermcheck(sp->owner, sp->perm, omode);
  131 
  132         cclose(c);
  133         incref(sp->chan);
  134         qunlock(&srvlk);
  135         poperror();
  136         return sp->chan;
  137 }
  138 
  139 static void
  140 srvcreate(Chan *c, char *name, int omode, ulong perm)
  141 {
  142         char *sname;
  143         Srv *sp;
  144 
  145         if(openmode(omode) != OWRITE)
  146                 error(Eperm);
  147 
  148         if(omode & OCEXEC)      /* can't happen */
  149                 panic("someone broke namec");
  150 
  151         sp = smalloc(sizeof *sp);
  152         sname = smalloc(strlen(name)+1);
  153 
  154         qlock(&srvlk);
  155         if(waserror()){
  156                 free(sp);
  157                 free(sname);
  158                 qunlock(&srvlk);
  159                 nexterror();
  160         }
  161         if(sp == nil || sname == nil)
  162                 error(Enomem);
  163         if(srvlookup(name, -1))
  164                 error(Eexist);
  165 
  166         sp->path = qidpath++;
  167         sp->link = srv;
  168         strcpy(sname, name);
  169         sp->name = sname;
  170         c->qid.type = QTFILE;
  171         c->qid.path = sp->path;
  172         srv = sp;
  173         qunlock(&srvlk);
  174         poperror();
  175 
  176         kstrdup(&sp->owner, up->user);
  177         sp->perm = perm&0777;
  178 
  179         c->flag |= COPEN;
  180         c->mode = OWRITE;
  181 }
  182 
  183 static void
  184 srvremove(Chan *c)
  185 {
  186         Srv *sp, **l;
  187 
  188         if(c->qid.type == QTDIR)
  189                 error(Eperm);
  190 
  191         qlock(&srvlk);
  192         if(waserror()){
  193                 qunlock(&srvlk);
  194                 nexterror();
  195         }
  196         l = &srv;
  197         for(sp = *l; sp; sp = sp->link) {
  198                 if(sp->path == c->qid.path)
  199                         break;
  200 
  201                 l = &sp->link;
  202         }
  203         if(sp == 0)
  204                 error(Enonexist);
  205 
  206         /*
  207          * Only eve can remove system services.
  208          * No one can remove #s/boot.
  209          */
  210         if(strcmp(sp->owner, eve) == 0 && !iseve())
  211                 error(Eperm);
  212         if(strcmp(sp->name, "boot") == 0)
  213                 error(Eperm);
  214 
  215         /*
  216          * No removing personal services.
  217          */
  218         if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve())
  219                 error(Eperm);
  220 
  221         *l = sp->link;
  222         qunlock(&srvlk);
  223         poperror();
  224 
  225         if(sp->chan)
  226                 cclose(sp->chan);
  227         free(sp->name);
  228         free(sp);
  229 }
  230 
  231 static int
  232 srvwstat(Chan *c, uchar *dp, int n)
  233 {
  234         char *strs;
  235         Dir d;
  236         Srv *sp;
  237 
  238         if(c->qid.type & QTDIR)
  239                 error(Eperm);
  240 
  241         strs = nil;
  242         qlock(&srvlk);
  243         if(waserror()){
  244                 qunlock(&srvlk);
  245                 free(strs);
  246                 nexterror();
  247         }
  248 
  249         sp = srvlookup(nil, c->qid.path);
  250         if(sp == 0)
  251                 error(Enonexist);
  252 
  253         if(strcmp(sp->owner, up->user) != 0 && !iseve())
  254                 error(Eperm);
  255 
  256         strs = smalloc(n);
  257         n = convM2D(dp, n, &d, strs);
  258         if(n == 0)
  259                 error(Eshortstat);
  260         if(d.mode != ~0UL)
  261                 sp->perm = d.mode & 0777;
  262         if(d.uid && *d.uid)
  263                 kstrdup(&sp->owner, d.uid);
  264         if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
  265                 if(strchr(d.name, '/') != nil)
  266                         error(Ebadchar);
  267                 kstrdup(&sp->name, d.name);
  268         }
  269         qunlock(&srvlk);
  270         free(strs);
  271         poperror();
  272         return n;
  273 }
  274 
  275 static void
  276 srvclose(Chan *c)
  277 {
  278         /*
  279          * in theory we need to override any changes in removability
  280          * since open, but since all that's checked is the owner,
  281          * which is immutable, all is well.
  282          */
  283         if(c->flag & CRCLOSE){
  284                 if(waserror())
  285                         return;
  286                 srvremove(c);
  287                 poperror();
  288         }
  289 }
  290 
  291 static long
  292 srvread(Chan *c, void *va, long n, vlong)
  293 {
  294         isdir(c);
  295         return devdirread(c, va, n, 0, 0, srvgen);
  296 }
  297 
  298 static long
  299 srvwrite(Chan *c, void *va, long n, vlong)
  300 {
  301         Srv *sp;
  302         Chan *c1;
  303         int fd;
  304         char buf[32];
  305 
  306         if(n >= sizeof buf)
  307                 error(Egreg);
  308         memmove(buf, va, n);    /* so we can NUL-terminate */
  309         buf[n] = 0;
  310         fd = strtoul(buf, 0, 0);
  311 
  312         c1 = fdtochan(fd, -1, 0, 1);    /* error check and inc ref */
  313 
  314         qlock(&srvlk);
  315         if(waserror()) {
  316                 qunlock(&srvlk);
  317                 cclose(c1);
  318                 nexterror();
  319         }
  320         if(c1->flag & (CCEXEC|CRCLOSE))
  321                 error("posted fd has remove-on-close or close-on-exec");
  322         if(c1->qid.type & QTAUTH)
  323                 error("cannot post auth file in srv");
  324         sp = srvlookup(nil, c->qid.path);
  325         if(sp == 0)
  326                 error(Enonexist);
  327 
  328         if(sp->chan)
  329                 error(Ebadusefd);
  330 
  331         sp->chan = c1;
  332         qunlock(&srvlk);
  333         poperror();
  334         return n;
  335 }
  336 
  337 Dev srvdevtab = {
  338         's',
  339         "srv",
  340 
  341         devreset,
  342         srvinit,        
  343         devshutdown,
  344         srvattach,
  345         srvwalk,
  346         srvstat,
  347         srvopen,
  348         srvcreate,
  349         srvclose,
  350         srvread,
  351         devbread,
  352         srvwrite,
  353         devbwrite,
  354         srvremove,
  355         srvwstat,
  356 };

Cache object: 4df50088131baa0b2a52d3207633607b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.