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/devenv.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 enum
    9 {
   10         Maxenvsize = 16300,
   11 };
   12 
   13 static Egrp     *envgrp(Chan *c);
   14 static int      envwriteable(Chan *c);
   15 
   16 static Egrp     confegrp;       /* global environment group containing the kernel configuration */
   17 
   18 static Evalue*
   19 envlookup(Egrp *eg, char *name, ulong qidpath)
   20 {
   21         Evalue *e;
   22         int i;
   23 
   24         for(i=0; i<eg->nent; i++){
   25                 e = eg->ent[i];
   26                 if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0))
   27                         return e;
   28         }
   29         return nil;
   30 }
   31 
   32 static int
   33 envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
   34 {
   35         Egrp *eg;
   36         Evalue *e;
   37 
   38         if(s == DEVDOTDOT){
   39                 devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp);
   40                 return 1;
   41         }
   42 
   43         eg = envgrp(c);
   44         rlock(eg);
   45         e = 0;
   46         if(name)
   47                 e = envlookup(eg, name, -1);
   48         else if(s < eg->nent)
   49                 e = eg->ent[s];
   50 
   51         if(e == 0) {
   52                 runlock(eg);
   53                 return -1;
   54         }
   55 
   56         /* make sure name string continues to exist after we release lock */
   57         kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
   58         devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
   59         runlock(eg);
   60         return 1;
   61 }
   62 
   63 static Chan*
   64 envattach(char *spec)
   65 {
   66         Chan *c;
   67         Egrp *egrp = nil;
   68 
   69         if(spec && *spec) {
   70                 if(strcmp(spec, "c") == 0)
   71                         egrp = &confegrp;
   72                 if(egrp == nil)
   73                         error(Ebadarg);
   74         }
   75 
   76         c = devattach('e', spec);
   77         c->aux = egrp;
   78         return c;
   79 }
   80 
   81 static Walkqid*
   82 envwalk(Chan *c, Chan *nc, char **name, int nname)
   83 {
   84         return devwalk(c, nc, name, nname, 0, 0, envgen);
   85 }
   86 
   87 static int
   88 envstat(Chan *c, uchar *db, int n)
   89 {
   90         if(c->qid.type & QTDIR)
   91                 c->qid.vers = envgrp(c)->vers;
   92         return devstat(c, db, n, 0, 0, envgen);
   93 }
   94 
   95 static Chan*
   96 envopen(Chan *c, int omode)
   97 {
   98         Egrp *eg;
   99         Evalue *e;
  100         int trunc;
  101 
  102         eg = envgrp(c);
  103         if(c->qid.type & QTDIR) {
  104                 if(omode != OREAD)
  105                         error(Eperm);
  106         }
  107         else {
  108                 trunc = omode & OTRUNC;
  109                 if(omode != OREAD && !envwriteable(c))
  110                         error(Eperm);
  111                 if(trunc)
  112                         wlock(eg);
  113                 else
  114                         rlock(eg);
  115                 e = envlookup(eg, nil, c->qid.path);
  116                 if(e == 0) {
  117                         if(trunc)
  118                                 wunlock(eg);
  119                         else
  120                                 runlock(eg);
  121                         error(Enonexist);
  122                 }
  123                 if(trunc && e->value) {
  124                         e->qid.vers++;
  125                         free(e->value);
  126                         e->value = 0;
  127                         e->len = 0;
  128                 }
  129                 if(trunc)
  130                         wunlock(eg);
  131                 else
  132                         runlock(eg);
  133         }
  134         c->mode = openmode(omode);
  135         c->flag |= COPEN;
  136         c->offset = 0;
  137         return c;
  138 }
  139 
  140 static void
  141 envcreate(Chan *c, char *name, int omode, ulong)
  142 {
  143         Egrp *eg;
  144         Evalue *e;
  145         Evalue **ent;
  146 
  147         if(c->qid.type != QTDIR)
  148                 error(Eperm);
  149 
  150         omode = openmode(omode);
  151         eg = envgrp(c);
  152 
  153         wlock(eg);
  154         if(waserror()) {
  155                 wunlock(eg);
  156                 nexterror();
  157         }
  158 
  159         if(envlookup(eg, name, -1))
  160                 error(Eexist);
  161 
  162         e = smalloc(sizeof(Evalue));
  163         e->name = smalloc(strlen(name)+1);
  164         strcpy(e->name, name);
  165 
  166         if(eg->nent == eg->ment){
  167                 eg->ment += 32;
  168                 ent = smalloc(sizeof(eg->ent[0])*eg->ment);
  169                 if(eg->nent)
  170                         memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
  171                 free(eg->ent);
  172                 eg->ent = ent;
  173         }
  174         e->qid.path = ++eg->path;
  175         e->qid.vers = 0;
  176         eg->vers++;
  177         eg->ent[eg->nent++] = e;
  178         c->qid = e->qid;
  179 
  180         wunlock(eg);
  181         poperror();
  182 
  183         c->offset = 0;
  184         c->mode = omode;
  185         c->flag |= COPEN;
  186 }
  187 
  188 static void
  189 envremove(Chan *c)
  190 {
  191         int i;
  192         Egrp *eg;
  193         Evalue *e;
  194 
  195         if(c->qid.type & QTDIR)
  196                 error(Eperm);
  197 
  198         eg = envgrp(c);
  199         wlock(eg);
  200         e = 0;
  201         for(i=0; i<eg->nent; i++){
  202                 if(eg->ent[i]->qid.path == c->qid.path){
  203                         e = eg->ent[i];
  204                         eg->nent--;
  205                         eg->ent[i] = eg->ent[eg->nent];
  206                         eg->vers++;
  207                         break;
  208                 }
  209         }
  210         wunlock(eg);
  211         if(e == 0)
  212                 error(Enonexist);
  213         free(e->name);
  214         if(e->value)
  215                 free(e->value);
  216         free(e);
  217 }
  218 
  219 static void
  220 envclose(Chan *c)
  221 {
  222         /*
  223          * cclose can't fail, so errors from remove will be ignored.
  224          * since permissions aren't checked,
  225          * envremove can't not remove it if its there.
  226          */
  227         if(c->flag & CRCLOSE)
  228                 envremove(c);
  229 }
  230 
  231 static long
  232 envread(Chan *c, void *a, long n, vlong off)
  233 {
  234         Egrp *eg;
  235         Evalue *e;
  236         ulong offset = off;
  237 
  238         if(c->qid.type & QTDIR)
  239                 return devdirread(c, a, n, 0, 0, envgen);
  240 
  241         eg = envgrp(c);
  242         rlock(eg);
  243         e = envlookup(eg, nil, c->qid.path);
  244         if(e == 0) {
  245                 runlock(eg);
  246                 error(Enonexist);
  247         }
  248 
  249         if(offset > e->len)     /* protects against overflow converting vlong to ulong */
  250                 n = 0;
  251         else if(offset + n > e->len)
  252                 n = e->len - offset;
  253         if(n <= 0)
  254                 n = 0;
  255         else
  256                 memmove(a, e->value+offset, n);
  257         runlock(eg);
  258         return n;
  259 }
  260 
  261 static long
  262 envwrite(Chan *c, void *a, long n, vlong off)
  263 {
  264         char *s;
  265         ulong len;
  266         Egrp *eg;
  267         Evalue *e;
  268         ulong offset = off;
  269 
  270         if(n <= 0)
  271                 return 0;
  272         if(offset > Maxenvsize || n > (Maxenvsize - offset))
  273                 error(Etoobig);
  274 
  275         eg = envgrp(c);
  276         wlock(eg);
  277         e = envlookup(eg, nil, c->qid.path);
  278         if(e == 0) {
  279                 wunlock(eg);
  280                 error(Enonexist);
  281         }
  282 
  283         len = offset+n;
  284         if(len > e->len) {
  285                 s = smalloc(len);
  286                 if(e->value){
  287                         memmove(s, e->value, e->len);
  288                         free(e->value);
  289                 }
  290                 e->value = s;
  291                 e->len = len;
  292         }
  293         memmove(e->value+offset, a, n);
  294         e->qid.vers++;
  295         eg->vers++;
  296         wunlock(eg);
  297         return n;
  298 }
  299 
  300 Dev envdevtab = {
  301         'e',
  302         "env",
  303 
  304         devreset,
  305         devinit,
  306         devshutdown,
  307         envattach,
  308         envwalk,
  309         envstat,
  310         envopen,
  311         envcreate,
  312         envclose,
  313         envread,
  314         devbread,
  315         envwrite,
  316         devbwrite,
  317         envremove,
  318         devwstat,
  319 };
  320 
  321 void
  322 envcpy(Egrp *to, Egrp *from)
  323 {
  324         int i;
  325         Evalue *ne, *e;
  326 
  327         rlock(from);
  328         to->ment = (from->nent+31)&~31;
  329         to->ent = smalloc(to->ment*sizeof(to->ent[0]));
  330         for(i=0; i<from->nent; i++){
  331                 e = from->ent[i];
  332                 ne = smalloc(sizeof(Evalue));
  333                 ne->name = smalloc(strlen(e->name)+1);
  334                 strcpy(ne->name, e->name);
  335                 if(e->value){
  336                         ne->value = smalloc(e->len);
  337                         memmove(ne->value, e->value, e->len);
  338                         ne->len = e->len;
  339                 }
  340                 ne->qid.path = ++to->path;
  341                 to->ent[i] = ne;
  342         }
  343         to->nent = from->nent;
  344         runlock(from);
  345 }
  346 
  347 void
  348 closeegrp(Egrp *eg)
  349 {
  350         int i;
  351         Evalue *e;
  352 
  353         if(decref(eg) == 0){
  354                 for(i=0; i<eg->nent; i++){
  355                         e = eg->ent[i];
  356                         free(e->name);
  357                         if(e->value)
  358                                 free(e->value);
  359                         free(e);
  360                 }
  361                 free(eg->ent);
  362                 free(eg);
  363         }
  364 }
  365 
  366 static Egrp*
  367 envgrp(Chan *c)
  368 {
  369         if(c->aux == nil)
  370                 return up->egrp;
  371         return c->aux;
  372 }
  373 
  374 static int
  375 envwriteable(Chan *c)
  376 {
  377         return iseve() || c->aux == nil;
  378 }
  379 
  380 /*
  381  *  to let the kernel set environment variables
  382  */
  383 void
  384 ksetenv(char *ename, char *eval, int conf)
  385 {
  386         Chan *c;
  387         char buf[2*KNAMELEN];
  388         
  389         snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
  390         c = namec(buf, Acreate, OWRITE, 0600);
  391         devtab[c->type]->write(c, eval, strlen(eval), 0);
  392         cclose(c);
  393 }
  394 
  395 /*
  396  * Return a copy of configuration environment as a sequence of strings.
  397  * The strings alternate between name and value.  A zero length name string
  398  * indicates the end of the list
  399  */
  400 char *
  401 getconfenv(void)
  402 {
  403         Egrp *eg = &confegrp;
  404         Evalue *e;
  405         char *p, *q;
  406         int i, n;
  407 
  408         rlock(eg);
  409         if(waserror()) {
  410                 runlock(eg);
  411                 nexterror();
  412         }
  413         
  414         /* determine size */
  415         n = 0;
  416         for(i=0; i<eg->nent; i++){
  417                 e = eg->ent[i];
  418                 n += strlen(e->name) + e->len + 2;
  419         }
  420         p = malloc(n + 1);
  421         if(p == nil)
  422                 error(Enomem);
  423         q = p;
  424         for(i=0; i<eg->nent; i++){
  425                 e = eg->ent[i];
  426                 strcpy(q, e->name);
  427                 q += strlen(q) + 1;
  428                 memmove(q, e->value, e->len);
  429                 q[e->len] = 0;
  430                 /* move up to the first null */
  431                 q += strlen(q) + 1;
  432         }
  433         *q = 0;
  434         
  435         poperror();
  436         runlock(eg);
  437         return p;
  438 }

Cache object: c77f0143b97cd2000c77b8cdfe5cd355


[ 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.