//+++2002-08-17 // Copyright (C) 2001,2002 Mike Rieker, Beverly, MA USA // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //---2002-08-17 /************************************************************************/ /* */ /* Logical name processing routines */ /* */ /************************************************************************/ #define _OZ_KNL_LOGNAME_C #include "ozone.h" #include "oz_knl_event.h" #include "oz_knl_kmalloc.h" #include "oz_knl_logname.h" #include "oz_knl_objtype.h" #include "oz_knl_printk.h" #include "oz_knl_procmode.h" #include "oz_knl_sdata.h" #include "oz_knl_status.h" #include "oz_knl_thread.h" #include "oz_knl_userjob.h" #include "oz_sys_xprintf.h" struct OZ_Logname { OZ_Objtype objtype; /* object type OZ_OBJTYPE_LOGNAME */ OZ_Logname *next; /* next name in table */ Long refcount; /* reference count (only use oz_hw_atomic_inc_long) */ OZ_Logname *lognamtbl; /* the logical table it is in */ int name_l; /* strlen (name) */ char *name; /* pointer to null terminated logical name string */ OZ_Procmode procmode; /* processor mode it is defined as */ OZ_Secattr *secattr; /* security attributes (who can access me) */ uLong lognamatr; /* logical name attribute flags */ OZ_Event *tablevent; /* logical name table locking event flag */ OZ_Logname *lognames; /* if table, pointer to list of logical names in the table */ uLong nvalues; /* number of entries in values table */ OZ_Logvalue values[1]; /* if not table, array of value attribute/buffer pairs */ }; /* followed by the rest of the values[] array elements */ /* followed by things pointed to by values[] array */ /* followed by the name string */ struct OZ_Lognamesearch { OZ_Objtype objtype; uLong name_lognamatr; uLong name_nvalues; const OZ_Logvalue *name_values; OZ_Logname *name_logname; uLong name_valuei; OZ_Lognamesearch *recurse; }; static uLong logname_search (int level, OZ_Lognamesearch **lognamesearch_r, OZ_Procmode procmode, const char *tablename, const char *name, OZ_Logname *logname, OZ_Logname **logname_r, uLong *index_r, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue **values_r, OZ_Logname **lognamtbl_r); static uLong logname_create (OZ_Logname *lognamtbl, OZ_Procmode procmode, OZ_Seckeys *seckeys, OZ_Secattr *secattr, uLong lognamatr, int name_l, const char *name, uLong nvalues, const OZ_Logvalue values[], OZ_Logname **logname_r); static uLong logname_lookup (OZ_Logname *given_lognamtbl, OZ_Procmode procmode, int given_name_l, const char *given_name, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue *values_r[], OZ_Logname **logname_r, OZ_Logname **lognamtbl_r, int level); static OZ_Logname *cvtlognamtblobj (OZ_Logname *lognamtbl); static uLong lognamtbl_lock (OZ_Logname *lognamtbl); static void lognamtbl_unlock (OZ_Logname *lognamtbl); static void markdelete (OZ_Logname *logname); /************************************************************************/ /* */ /* Search recursively and repetitively through the tables for a */ /* logical name. Return the values one at a time. */ /* */ /* Input: */ /* */ /* *lognamesearch_r = NULL : initialize, return first value */ /* procmode = don't return anything at an outer mode than this */ /* tablename = NULL : search OZ_PROCESS_DIRECTORY then OZ_SYSTEM_DIRECTORY /* else : table name to search (can be a list logical) */ /* name = name to search for (can be recursive, can be a list)*/ /* value_r = where to return value string pointer */ /* logname_r = where to return logical name block pointer */ /* */ /* Output: */ /* */ /* oz_knl_logname_search = OZ_SUCCESS : value found */ /* **value_r = value */ /* *logname_r = logname struct */ /* (its refc has been incd) */ /* OZ_NOLOGNAM : value not found, no more values /* else : error status */ /* */ /* Note: */ /* */ /* if both value_r and logname_r are NULL, any search context is */ /* released */ /* */ /************************************************************************/ uLong oz_knl_logname_search (OZ_Lognamesearch **lognamesearch_r, OZ_Procmode procmode, const char *tablename, const char *name, OZ_Logname **logname_r, uLong *index_r, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue **values_r, OZ_Logname **lognamtbl_r) { return (logname_search (OZ_LOGNAME_MAXLEVEL, lognamesearch_r, procmode, tablename, name, NULL, logname_r, index_r, procmode_r, lognamatr_r, nvalues_r, values_r, lognamtbl_r)); } static uLong logname_search (int level, OZ_Lognamesearch **lognamesearch_r, OZ_Procmode procmode, const char *tablename, const char *name, OZ_Logname *logname, OZ_Logname **logname_r, uLong *index_r, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue **values_r, OZ_Logname **lognamtbl_r) { const OZ_Logvalue *name_values, *table_values; uLong i, name_lognamatr, name_nvalues, sts, table_lognamatr, table_nvalues; OZ_Logname *name_logname, *obj_logname, *table_logname; OZ_Lognamesearch *lns; lns = *lognamesearch_r; OZ_KNL_CHKOBJTYPE (lns, OZ_OBJTYPE_LOGNAMESEARCH); if (level < 0) return (OZ_EXMAXLOGNAMLVL); if ((lns == NULL) && ((logname_r != NULL) || (values_r != NULL))) { if (logname != NULL) name_logname = logname; else { /* If table name not given, use OZ_{PROCESS,JOB,USER,SYSTEM}_DIRECTORY */ if (tablename == NULL) { for (i = 0; i < sizeof oz_s_logname_directorynames / sizeof oz_s_logname_directorynames[0]; i ++) { sts = logname_search (level - 1, lognamesearch_r, procmode, oz_s_logname_directorynames[i], name, NULL, logname_r, index_r, procmode_r, lognamatr_r, nvalues_r, values_r, lognamtbl_r); if (sts != OZ_NOLOGNAME) break; } return (sts); } /* Otherwise, scan the directories for the given tablename. If not found, there's nothing we can do */ sts = oz_knl_logname_lookup (NULL, procmode, strlen (tablename), tablename, NULL, &table_lognamatr, &table_nvalues, &table_values, &table_logname, NULL); if (sts != OZ_SUCCESS) return (sts); /* If it is a table, look for the requested logical name. Return on any failure. */ /* In any case, we are done with 'table_logname' pointer, so dec table ref count. */ sts = oz_knl_logname_lookup (table_logname, procmode, strlen (name), name, NULL, &name_lognamatr, &name_nvalues, &name_values, &name_logname, NULL); oz_knl_logname_increfc (table_logname, -1); if (sts != OZ_SUCCESS) return (sts); } /* The name was found in that table, so make a search context block so we will return the logical's value array. */ /* Leave the logical's ref count incremented so it doesn't disappear on us. */ lns = OZ_KNL_PGPMALLOQ (sizeof *lns); /* allocate the block */ if (lns == NULL) return (OZ_EXQUOTAPGP); lns -> objtype = OZ_OBJTYPE_LOGNAMESEARCH; lns -> name_lognamatr = name_lognamatr; /* the attribute bits */ lns -> name_nvalues = name_nvalues; /* number of elements in 'values' array */ lns -> name_values = name_values; /* pointer to 'values' array */ lns -> name_logname = name_logname; /* pointer to logname struct */ lns -> name_valuei = 0; /* index of first value to return */ lns -> recurse = NULL; /* we haven't recursed yet */ *lognamesearch_r = lns; } /* If they are forcing a reset or we have reached the end of the value list, release context block and return 'No Logical Name' status */ /* If the logical is a table, we pretend it has exactly 1 value */ if (((values_r == NULL) && (logname_r == NULL)) || (lns -> name_valuei >= ((lns -> name_lognamatr & OZ_LOGNAMATR_TABLE) ? 1 : lns -> name_nvalues))) { if (lns != NULL) { /* see if context block exists */ logname_search (0, &(lns -> recurse), procmode, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); /* if so, release any recursion */ oz_knl_logname_increfc (lns -> name_logname, -1); /* release the logical name pointer */ OZ_KNL_PGPFREE (lns); /* free off the logical name block */ *lognamesearch_r = NULL; /* tell caller we have no more context block */ } return (OZ_NOLOGNAME); } /* If logical value is not terminal, do a recursive search */ /* If no recursive value found, pretend it was terminal */ if (!(lns -> name_lognamatr & OZ_LOGNAMATR_TABLE) && !(lns -> name_values[lns->name_valuei].attr & OZ_LOGVALATR_TERMINAL)) { if (lns -> name_values[lns->name_valuei].attr & OZ_LOGVALATR_OBJECT) { obj_logname = lns -> name_values[lns->name_valuei++].buff; /* get pointer to object */ if (OZ_KNL_GETOBJTYPE (obj_logname) == OZ_OBJTYPE_LOGNAME) { /* see if it is a logical name object */ oz_knl_logname_increfc (obj_logname, 1); /* ok, process that logical name */ sts = logname_search (level - 1, &(lns -> recurse), procmode, tablename, NULL, obj_logname, logname_r, index_r, procmode_r, lognamatr_r, nvalues_r, values_r, lognamtbl_r); if (sts != OZ_NOLOGNAME) return (sts); } } else { sts = logname_search (level - 1, &(lns -> recurse), procmode, tablename, lns -> name_values[lns->name_valuei++].buff, NULL, logname_r, index_r, procmode_r, lognamatr_r, nvalues_r, values_r, lognamtbl_r); if (sts != OZ_NOLOGNAME) return (sts); } lns -> name_valuei --; } /* Name is terminal, return value entry and increment value index for next time */ name_logname = lns -> name_logname; if (logname_r != NULL) *logname_r = name_logname; if (index_r != NULL) *index_r = lns -> name_valuei ++; if (procmode_r != NULL) *procmode_r = name_logname -> procmode; if (lognamatr_r != NULL) *lognamatr_r = name_logname -> lognamatr; if (nvalues_r != NULL) *nvalues_r = name_logname -> nvalues; if (values_r != NULL) *values_r = name_logname -> values; if (lognamtbl_r != NULL) *lognamtbl_r = name_logname -> lognamtbl; return (OZ_SUCCESS); } /************************************************************************/ /* */ /* Create logical name and put in logical name table */ /* */ /* Input: */ /* */ /* lognamtbl = logical name table to put logical in */ /* NULL to not put in any table */ /* (used for creating directories) */ /* procmode = processor mode to create logical at */ /* lognamatr = attributes to give logical name */ /* name = logical name string */ /* nvalues = number of values in array */ /* values = pointer to value array */ /* */ /* Output: */ /* */ /* oz_knl_logname_create = OZ_SUCCESS : new name created */ /* OZ_SUPERSEDED : old name superseded */ /* else : error status */ /* *logname_r = pointer to logical name struct created/superseded */ /* */ /************************************************************************/ uLong oz_knl_logname_creobj (OZ_Logname *lognamtbl, OZ_Procmode procmode, OZ_Seckeys *seckeys, OZ_Secattr *secattr, uLong lognamatr, int name_l, const char *name, void *object, OZ_Logname **logname_r) { OZ_Logvalue value; value.attr = OZ_LOGVALATR_OBJECT; value.buff = object; return (logname_create (lognamtbl, procmode, seckeys, secattr, lognamatr, name_l, name, 1, &value, logname_r)); } uLong oz_knl_logname_crestr (OZ_Logname *lognamtbl, OZ_Procmode procmode, OZ_Seckeys *seckeys, OZ_Secattr *secattr, uLong lognamatr, int name_l, const char *name, const char *string, OZ_Logname **logname_r) { OZ_Logvalue value; value.attr = 0; value.buff = (void *)string; return (logname_create (lognamtbl, procmode, seckeys, secattr, lognamatr, name_l, name, 1, &value, logname_r)); } uLong oz_knl_logname_create (OZ_Logname *lognamtbl, OZ_Procmode procmode, OZ_Seckeys *seckeys, OZ_Secattr *secattr, uLong lognamatr, int name_l, const char *name, uLong nvalues, const OZ_Logvalue values[], OZ_Logname **logname_r) { return (logname_create (lognamtbl, procmode, seckeys, secattr, lognamatr, name_l, name, nvalues, values, logname_r)); } static uLong logname_create (OZ_Logname *given_lognamtbl, OZ_Procmode procmode, OZ_Seckeys *seckeys, OZ_Secattr *secattr, uLong lognamatr, int given_name_l, const char *given_name, uLong nvalues, const OZ_Logvalue values[], OZ_Logname **logname_r) { char *cp, *q; const char *name; int cmp, name_l; uLong i, sts, totalsize; OZ_Event *tablevent; OZ_Logname **llogname, *logname, *lognamtbl, *nlogname, *xlogname; void *object; xlogname = NULL; /* If table attribute (ie, creating a table), nvalues must be zero */ if ((lognamatr & OZ_LOGNAMATR_TABLE) && (nvalues != 0)) return (OZ_LOGNAMTBLNZ); /* Make sure logical name itself is not too big */ given_name_l = strnlen (given_name, given_name_l); totalsize = given_name_l + 1; if (totalsize > OZ_LOGNAME_MAXNAMSZ) return (OZ_LOGNAMETOOBIG); /* Check size of the array (+1 accounts for the null string terminators) */ if (nvalues > OZ_LOGNAME_SIZEMAX / (sizeof *values + 1)) return (OZ_LOGNAMETOOBIG); totalsize += nvalues * (sizeof *values + 1); /* Make sure the total size of all strings won't be too big */ for (i = 0; i < nvalues; i ++) { if (values[i].attr & OZ_LOGVALATR_OBJECT) { sts = oz_knl_logname_incobjrefc (values[i].buff, 0, NULL); /* object type doesn't consume space */ if (sts != OZ_SUCCESS) return (sts); /* but let's validate it while we're here */ } else { totalsize += strlen (values[i].buff); /* strings consume space */ } if (totalsize > OZ_LOGNAME_SIZEMAX) return (OZ_LOGNAMETOOBIG); } /* Get table to be used indicated in the name itself. Note that this increments the table's ref count no matter if it is the given table or not. */ sts = oz_knl_logname_parse (given_lognamtbl, procmode, given_name_l, given_name, &lognamtbl, &name_l, &name); if (sts != OZ_SUCCESS) return (sts); /* Determine table and lock it - if the given table name is a list of tables, use the first one */ if (lognamtbl != NULL) { for (i = OZ_LOGNAME_MAXLEVEL; i > 0; i --) { /* only nest this many times */ if (lognamtbl -> lognamatr & OZ_LOGNAMATR_TABLE) goto gottable; /* if we're at a table, we're done */ if (lognamtbl -> nvalues == 0) { /* not a table, it must have values */ sts = OZ_NOLOGNAME; goto rtn_decrefc; } if (lognamtbl -> values[0].attr & OZ_LOGVALATR_OBJECT) { /* ok, see if first value is an object */ logname = lognamtbl -> values[0].buff; /* get pointer to the object */ logname = cvtlognamtblobj (logname); /* convert to corresponding logical name */ if (logname == NULL) { sts = OZ_INVOBJTYPE; /* - some wacky type of object that doesn't have a table */ goto rtn_decrefc; } oz_knl_logname_increfc (logname, 1); /* ok, increment the table's ref count */ } else { sts = logname_lookup (NULL, procmode, strlen (lognamtbl -> values[0].buff), lognamtbl -> values[0].buff, NULL, NULL, NULL, NULL, &logname, NULL, i - 1); if (sts != OZ_SUCCESS) goto rtn_decrefc; /* name of a table, look up the table in the directories & inc its ref count */ } oz_knl_logname_increfc (lognamtbl, -1); /* done with previous table */ lognamtbl = logname; /* use this logical as the table */ } sts = OZ_EXMAXLOGNAMLVL; goto rtn_decrefc; gottable: sts = oz_knl_security_check (OZ_SECACCMSK_WRITE, seckeys, lognamtbl -> secattr); /* got table, make sure caller can write it */ if (sts == OZ_SUCCESS) sts = lognamtbl_lock (lognamtbl); /* caller can write it, lock it */ if (sts != OZ_SUCCESS) goto rtn_decrefc; } /* Search for the name already in the table - */ /* If one exists at same access mode that is marked NOSUPERSEDE, return error status */ /* If one exists at inner access mode that is marked NOOUTERMODE, return error status */ if (lognamtbl != NULL) { for (logname = lognamtbl -> lognames; logname != NULL; logname = logname -> next) { /* scan all logicals in table */ if (logname -> name_l != name_l) continue; if (memcmp (logname -> name, name, name_l) != 0) continue; /* skip it if the name doesn't match */ if (logname -> procmode == procmode) { /* see if exact procmode match */ if (logname -> lognamatr & OZ_LOGNAMATR_NOSUPERSEDE) { /* match, maybe existing logical can't be superseded */ sts = OZ_NOSUPERSEDE; logname = NULL; goto unlock_it; } OZ_HW_ATOMIC_INCBY1_LONG (logname -> refcount); /* it can be superseded, inc its ref count */ markdelete (logname); /* mark for delete (ie, remove from table) */ logname -> next = xlogname; /* link to list of superseded logicals */ xlogname = logname; continue; } if ((logname -> procmode < procmode) && (logname -> lognamatr & OZ_LOGNAMATR_NOOUTERMODE)) { /* old lnm more privileged, see if it allows outermode lnm's */ sts = OZ_NOOUTERMODE; /* if not, it is an error */ logname = NULL; goto unlock_it; } if ((lognamatr & OZ_LOGNAMATR_NOOUTERMODE) && (logname -> procmode > procmode)) { /* old lnm less privd and new doesn't allow outermodes, */ OZ_HW_ATOMIC_INCBY1_LONG (logname -> refcount); /* ... supersede it */ markdelete (logname); logname -> next = xlogname; xlogname = logname; } } } sts = OZ_SUCCESS; if (xlogname != NULL) sts = OZ_SUPERSEDED; /* Allocate a buffer that is large enough to hold the name and all the values */ logname = OZ_KNL_PGPMALLOQ (totalsize + sizeof *logname); if (logname == NULL) { sts = OZ_EXQUOTAPGP; goto unlock_it; } /* If we are creating a table, create table's locking event flag */ tablevent = NULL; if (lognamatr & OZ_LOGNAMATR_TABLE) { sts = oz_knl_event_create (21, "oz_knl_logname create", NULL, &tablevent); if (sts != OZ_SUCCESS) { OZ_KNL_PGPFREE (logname); goto unlock_it; } oz_knl_event_set (tablevent, 1); } /* Point to where the the character strings will go (they follow the values array) */ cp = (char *)(logname -> values + nvalues); /* Fill in fixed part of block */ logname -> objtype = OZ_OBJTYPE_LOGNAME; logname -> name_l = name_l; logname -> name = cp; logname -> procmode = procmode; logname -> secattr = secattr; logname -> lognamatr = lognamatr; logname -> tablevent = tablevent; logname -> lognames = NULL; logname -> nvalues = nvalues; logname -> refcount = 1; oz_knl_secattr_increfc (logname -> secattr, 1); /* Put the name in */ memcpy (cp, name, name_l); cp += name_l; *(cp ++) = 0; /* Link to its logical name table */ logname -> next = NULL; logname -> lognamtbl = lognamtbl; if (lognamtbl != NULL) { for (llogname = &(lognamtbl -> lognames); (nlogname = *llogname) != NULL; llogname = &(nlogname -> next)) { cmp = strcmp (nlogname -> name, logname -> name); if (cmp < 0) continue; if (cmp > 0) break; if (nlogname -> procmode > logname -> procmode) break; } *llogname = logname; logname -> next = nlogname; } /* Copy the values (if table, nvalues is zero) */ for (i = 0; i < nvalues; i ++) { /* loop through the values array */ logname -> values[i].attr = values[i].attr; /* copy the attributes */ if (logname -> values[i].attr & OZ_LOGVALATR_OBJECT) { /* see if it is an object pointer */ logname -> values[i].buff = values[i].buff; /* if so, just use pointer to object as is */ } else { strcpy (cp, values[i].buff); /* just a string, copy it in */ logname -> values[i].buff = cp; /* set up pointer to character string */ cp += strlen (cp) + 1; /* point just past the terminating null */ } } unlock_it: if (lognamtbl != NULL) lognamtbl_unlock (lognamtbl); /* unlock parent table */ /* now that parent table is unlocked it is ok to increment object ref counts */ /* just in case an object count being incremented is the table itself we can't deadlock */ if (logname != NULL) { for (i = 0; i < logname -> nvalues; i ++) { /* loop through the values array */ if (logname -> values[i].attr & OZ_LOGVALATR_OBJECT) { /* see if object-type value */ sts = oz_knl_logname_getobj (logname, i, OZ_OBJTYPE_UNKNOWN, &object); /* inc its reference count */ if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname_create: error %u incing object %s ref count", sts, logname -> values[i].buff); } } } /* Return pointer if caller wants it - if not dec logicals ref count (its in the table with ref count 0) */ if (logname_r != NULL) *logname_r = logname; else if (logname != NULL) oz_knl_logname_increfc (logname, -1); rtn_decrefc: if (lognamtbl != NULL) oz_knl_logname_increfc (lognamtbl, -1); /* this was incd by the logname_parse routine */ while ((logname = xlogname) != NULL) { /* finish deleting any superseded logicals */ xlogname = logname -> next; oz_knl_logname_increfc (logname, -1); } return (sts); /* return completion status */ } /************************************************************************/ /* */ /* Lookup a logical name */ /* */ /* Input: */ /* */ /* lognamtbl = NULL : use process then system directories */ /* else : pointer to logical name table */ /* procmode = processor mode of outermost name to consider */ /* seckeys = security keys to access logical with */ /* name = logical name to search for */ /* */ /* Output: */ /* */ /* oz_knl_logname_lookup = OZ_SUCCESS : name was found */ /* else : error status */ /* *procmode_r = processor mode of name found */ /* *lognamatr_r = logical name attributes */ /* *nvalues_r = number of values for the name */ /* *values_r = pointer to value list array */ /* *logname_r = pointer to logical name entry */ /* *lognamtbl_r = pointer to table it was found in */ /* */ /* Note: */ /* */ /* logical name ref count incremented iff logname_r is not NULL */ /* logical table ref count incremented iff lognamtbl_r is not NULL */ /* */ /************************************************************************/ uLong oz_knl_logname_lookup (OZ_Logname *lognamtbl, OZ_Procmode procmode, int name_l, const char *name, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue *values_r[], OZ_Logname **logname_r, OZ_Logname **lognamtbl_r) { return (logname_lookup (lognamtbl, procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, OZ_LOGNAME_MAXLEVEL)); } /* 'level' is used for recursive calls to keep from going too deep */ static uLong logname_lookup (OZ_Logname *given_lognamtbl, OZ_Procmode procmode, int given_name_l, const char *given_name, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue *values_r[], OZ_Logname **logname_r, OZ_Logname **lognamtbl_r, int level) { const char *name; int name_l; OZ_Logname *logname, *lognamtbl, *outermost_logname; OZ_Procmode outermost_procmode; uLong i, sts; void *object; OZ_KNL_CHKOBJTYPE (given_lognamtbl, OZ_OBJTYPE_LOGNAME); if (logname_r != NULL) *logname_r = NULL; if (lognamtbl_r != NULL) *lognamtbl_r = NULL; if (level < 0) return (OZ_EXMAXLOGNAMLVL); /* Get table to be used indicated in the name itself. Note that this increments the table's ref count no matter if it is the given table or not */ sts = oz_knl_logname_parse (given_lognamtbl, procmode, given_name_l, given_name, &lognamtbl, &name_l, &name); if (sts != OZ_SUCCESS) return (sts); /* If lognamtbl is null, it means to search the directories */ if (lognamtbl == NULL) { /* Maybe they are trying to access the directories themselves */ if ((oz_s_logname_directorynames[0][name_l] == 0) && (memcmp (name, oz_s_logname_directorynames[0], name_l) == 0)) { logname = oz_knl_process_getlognamdir (NULL); goto found_it; } if ((oz_s_logname_directorynames[1][name_l] == 0) && (memcmp (name, oz_s_logname_directorynames[1], name_l) == 0)) { logname = oz_knl_job_getlognamdir (NULL); goto found_it; } if ((oz_s_logname_directorynames[2][name_l] == 0) && (memcmp (name, oz_s_logname_directorynames[2], name_l) == 0)) { logname = oz_knl_user_getlognamdir (NULL); goto found_it; } if ((oz_s_logname_directorynames[3][name_l] == 0) && (memcmp (name, oz_s_logname_directorynames[3], name_l) == 0)) { logname = oz_s_systemdirectory; goto found_it; } /* Not the directories themselves, search the directories for the name */ sts = logname_lookup (oz_knl_process_getlognamdir (NULL), procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, level - 1); if (sts == OZ_NOLOGNAME) sts = logname_lookup (oz_knl_job_getlognamdir (NULL), procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, level - 1); if (sts == OZ_NOLOGNAME) sts = logname_lookup (oz_knl_user_getlognamdir (NULL), procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, level - 1); if (sts == OZ_NOLOGNAME) sts = logname_lookup (oz_s_systemdirectory, procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, level - 1); return (sts); } /* If lognamtbl is not a table itself, then try to get tables named of its values */ if (!(lognamtbl -> lognamatr & OZ_LOGNAMATR_TABLE)) { /* Loop through each value */ sts = OZ_NOLOGNAME; for (i = 0; i < lognamtbl -> nvalues; i ++) { /* If lognamtbl is an object logical of a logical, use the object as the table to search in */ if (lognamtbl -> values[i].attr & OZ_LOGVALATR_OBJECT) { sts = oz_knl_logname_getobj (lognamtbl, i, OZ_OBJTYPE_UNKNOWN, &object); /* get the object pointer */ if (sts == OZ_SUCCESS) { logname = cvtlognamtblobj (object); /* try to convert to a table pointer (if it's not already) */ if (logname == NULL) sts = OZ_INVOBJTYPE; /* - maybe it's something that doesn't have a table */ else oz_knl_logname_increfc (logname, 1); /* - it converted to a table, inc table's ref count */ oz_knl_logname_incobjrefc (object, -1, NULL); /* anyway, decrement object's ref count */ } } /* Find table with that name in the directories */ else sts = logname_lookup (NULL, procmode, strlen (lognamtbl -> values[i].buff), lognamtbl -> values[i].buff, NULL, NULL, NULL, NULL, &logname, NULL, level - 1); /* If found, use that table to lookup requested logical name */ if (sts == OZ_SUCCESS) { sts = logname_lookup (logname, procmode, name_l, name, procmode_r, lognamatr_r, nvalues_r, values_r, logname_r, lognamtbl_r, level - 1); oz_knl_logname_increfc (logname, -1); } /* If found (or some weird error), return status */ if (sts != OZ_NOLOGNAME) break; /* Not found in that table, try another */ /* If tried all associated tables, return 'no such logical name' */ } oz_knl_logname_increfc (lognamtbl, -1); return (sts); } /* It is a table, lock it */ sts = lognamtbl_lock (lognamtbl); if (sts != OZ_SUCCESS) { oz_knl_logname_increfc (lognamtbl, -1); return (sts); } /* Search table for name. Get the outermost name that is at or inside the given procmode. */ outermost_procmode = OZ_PROCMODE_KNL; outermost_logname = NULL; for (logname = lognamtbl -> lognames; logname != NULL; logname = logname -> next) { if ((logname -> name_l == name_l) && (memcmp (logname -> name, name, name_l) == 0)) { if (logname -> procmode == procmode) goto found_it; if ((logname -> procmode < procmode) && (logname -> procmode >= outermost_procmode)) { outermost_procmode = logname -> procmode; outermost_logname = logname; } } } logname = outermost_logname; sts = OZ_NOLOGNAME; if (logname == NULL) goto unlock_it; found_it: /* If pointer to name was requested, inc the reference count */ if (logname_r != NULL) { *logname_r = logname; OZ_HW_ATOMIC_INCBY1_LONG (logname -> refcount); } /* If pointer to table was requested, inc the reference count */ if (lognamtbl_r != NULL) { *lognamtbl_r = lognamtbl; oz_knl_logname_increfc (lognamtbl, 1); } /* Anyway, return any other things requested */ if (procmode_r != NULL) *procmode_r = logname -> procmode; if (lognamatr_r != NULL) *lognamatr_r = logname -> lognamatr; if (nvalues_r != NULL) *nvalues_r = logname -> nvalues; if (values_r != NULL) *values_r = logname -> values; sts = OZ_SUCCESS; unlock_it: if (lognamtbl != NULL) { lognamtbl_unlock (lognamtbl); oz_knl_logname_increfc (lognamtbl, -1); } return (sts); } /************************************************************************/ /* */ /* Parse a logical name into its table and name components */ /* */ /* Input: */ /* */ /* lognamtbl = default table pointer */ /* (or NULL for list of directories) */ /* procmode = outermost processor mode to consider */ /* name = logical name to be parsed */ /* */ /* Output: */ /* */ /* oz_knl_logname_parse = OZ_SUCCESS : parse successful */ /* else : error status */ /* *lognamtbl_r = resultant table pointer (ref count incd) */ /* *name_r = pointer to name portion of input string */ /* */ /* Note: */ /* */ /* Caller may supply the name of a Process, Job or User objtype */ /* logical name, which refers to the corresponding directory. */ /* */ /************************************************************************/ uLong oz_knl_logname_parse (OZ_Logname *lognamtbl, OZ_Procmode procmode, int name_l, const char *name, OZ_Logname **lognamtbl_r, int *name_l_r, const char **name_r) { const char *p; uLong sts; OZ_Logname *logname; name_l = strnlen (name, name_l); for (p = name + name_l; (-- p) > name;) if (*p == OZ_LOGNAME_TABLECHR) break; if (*p == OZ_LOGNAME_TABLECHR) { sts = oz_knl_logname_lookup (NULL, procmode, p - name, name, NULL, NULL, NULL, NULL, &logname, NULL); /* look up table in directories */ if (sts == OZ_SUCCESS) { lognamtbl = cvtlognamtblobj (logname); /* convert to table pointer if necessary */ if (lognamtbl == NULL) sts = OZ_INVOBJTYPE; /* error if it won't convert */ else oz_knl_logname_increfc (lognamtbl, 1); /* inc table's ref count if it did convert */ oz_knl_logname_increfc (logname, -1); /* converted or not, done with logname */ *lognamtbl_r = lognamtbl; /* return pointer to table */ *name_r = ++ p; /* return pointer to name string (skip over the % first) */ *name_l_r = name + name_l - p; /* return length of name string */ } return (sts); /* return table lookup status */ } /* No table name specified, use given table */ *name_l_r = name_l; /* return whole name string */ *name_r = name; /* Now if it's really a table, just use it as is. */ /* But it may be a process, job, or user block, and if so, get corresponding directory */ sts = OZ_SUCCESS; /* by default, successful */ if (lognamtbl != NULL) { lognamtbl = cvtlognamtblobj (lognamtbl); /* lognamtbl given (or something than can convert to a table pointer), convert to table pointer if necessary */ if (lognamtbl == NULL) sts = OZ_INVOBJTYPE; /* error if it won't convert */ else oz_knl_logname_increfc (lognamtbl, 1); /* inc table's ref count if it did convert */ } *lognamtbl_r = lognamtbl; /* return table pointer (or NULL if failure) */ return (sts); /* return status */ } /************************************************************************/ /* */ /* Convert logical name object entry to a printable string */ /* */ /* Input: */ /* */ /* logname = pointer to logical name */ /* index = index of value to process */ /* */ /* Output: */ /* */ /* oz_knl_logname_objstr = OZ_SUCCESS : successful */ /* OZ_BUFFEROVF : output buffer overflowed */ /* OZ_SUBSCRIPT : 'index' is too big */ /* OZ_NOTLOGNAMOBJ : not an object logname */ /* *buffer = filled in with null-terminated string */ /* */ /************************************************************************/ uLong oz_knl_logname_objstr (OZ_Logname *logname, uLong index, int buflen, char *buffer) { char *objtypstr, tmpbuf[sizeof(OZ_Pointer)*2+32]; int i; OZ_Pointer object; uLong sts; OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); if (index >= logname -> nvalues) return (OZ_SUBSCRIPT); /* Make sure it is an object type value */ if (!(logname -> values[index].attr & OZ_LOGVALATR_OBJECT)) return (OZ_NOTLOGNAMOBJ); /* Convert to a string in the form : */ sts = oz_knl_logname_incobjrefc (logname -> values[index].buff, 0, &objtypstr); if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname objstr: bad object in %s index %u", logname -> name, index); i = sizeof tmpbuf - strlen (objtypstr) - 1; strcpy (tmpbuf + i, objtypstr); tmpbuf[--i] = ':'; object = (OZ_Pointer)(logname -> values[index].buff); do { tmpbuf[--i] = "0123456789ABCDEF"[object&15]; object >>= 4; } while (object != 0); strncpyz (buffer, tmpbuf + i, buflen); if (sizeof tmpbuf - i >= buflen) sts = OZ_BUFFEROVF; return (sts); } /************************************************************************/ /* */ /* Get the object associated with a logical name */ /* */ /* Input: */ /* */ /* logname = pointer to logical name with the OBJECT attribute */ /* index = value index */ /* objtype = the object's type */ /* OZ_OBJTYPE_UNKNOWN, caller must determine type */ /* */ /* Output: */ /* */ /* oz_knl_logname_getobj = OZ_SUCCESS : successful */ /* else : error status */ /* *object_r = object pointer */ /* its ref count has been incremented */ /* */ /************************************************************************/ uLong oz_knl_logname_getobj (OZ_Logname *logname, uLong index, OZ_Objtype objtype, void **object_r) { uLong sts; void *object; OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); /* Make sure value index is in range */ if (index >= logname -> nvalues) return (OZ_SUBSCRIPT); /* Make sure it is an object type value */ if (!(logname -> values[index].attr & OZ_LOGVALATR_OBJECT)) return (OZ_NOTLOGNAMOBJ); /* Ok, get the object pointer and increment reference count */ object = logname -> values[index].buff; /* get pointer to object */ if ((objtype != OZ_OBJTYPE_UNKNOWN) && (OZ_KNL_GETOBJTYPE (object) != objtype)) { /* make sure it is the type they expect */ oz_knl_printk ("oz_knl_logname_getobj: logname %s index %u object %p is type %d, not %d\n", logname -> name, index, object, OZ_KNL_GETOBJTYPE (object), objtype); return (OZ_BADLOGNOBJTYPE); } sts = oz_knl_logname_incobjrefc (object, 1, NULL); /* ok, inc its reference count */ if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname_getobj: error %u incing ref count of object %s", sts, logname -> name); *object_r = object; /* return pointer to object */ return (OZ_SUCCESS); /* return final status */ } /************************************************************************/ /* */ /* Get the value array associated with a logical name */ /* */ /* Input: */ /* */ /* logname = pointer to logical name */ /* */ /* Output: */ /* */ /* oz_knl_logname_getval = OZ_SUCCESS : successful */ /* else : error status */ /* *lognamatr_r = logical name attributes */ /* *nvalues_r = number of elements in array */ /* *values_r = pointer to value array */ /* *lognamtbl_r = logical name table pointer */ /* */ /* Note: */ /* */ /* if lognamtbl_r is not NULL, the table's ref count is */ /* incremented */ /* */ /************************************************************************/ uLong oz_knl_logname_getval (OZ_Logname *logname, OZ_Procmode *procmode_r, uLong *lognamatr_r, uLong *nvalues_r, const OZ_Logvalue *values_r[], OZ_Logname **lognamtbl_r) { OZ_Logname *lognamtbl; OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); if (lognamtbl_r != NULL) { lognamtbl = logname -> lognamtbl; if (lognamtbl != NULL) oz_knl_logname_increfc (lognamtbl, 1); *lognamtbl_r = lognamtbl; } if (procmode_r != NULL) *procmode_r = logname -> procmode; if (lognamatr_r != NULL) *lognamatr_r = logname -> lognamatr; if (nvalues_r != NULL) *nvalues_r = logname -> nvalues; if (values_r != NULL) *values_r = logname -> values; return (OZ_SUCCESS); } /************************************************************************/ /* */ /* Get first/next logical name in a table */ /* */ /* Input: */ /* */ /* lognamtbl = logical name table pointer */ /* *logname_r = previous logical name or NULL if first one */ /* */ /* Output: */ /* */ /* oz_knl_logname_gettblent = OZ_SUCCESS : successful */ /* else : error status */ /* *logname_r = new logical name or NULL if end of table */ /* */ /* Note: */ /* */ /* *logname_r's ref count is decremented on input and incremented */ /* on output */ /* */ /************************************************************************/ uLong oz_knl_logname_gettblent (OZ_Logname *lognamtbl, OZ_Logname **logname_r) { uLong sts; OZ_Logname *newlogname, *oldlogname; oldlogname = *logname_r; /* get input logical name pointer */ if (oldlogname != NULL) { OZ_KNL_CHKOBJTYPE (oldlogname, OZ_OBJTYPE_LOGNAME); lognamtbl = oldlogname -> lognamtbl; /* ... if present, get its table */ if (lognamtbl == NULL) return (OZ_LOGNAMNOTINTBL); } else { lognamtbl = cvtlognamtblobj (lognamtbl); /* try to get a real table */ if (lognamtbl == NULL) return (OZ_INVOBJTYPE); } sts = lognamtbl_lock (lognamtbl); /* keep others out of table while we link to next in table */ if (sts != OZ_SUCCESS) return (sts); if (oldlogname != NULL) newlogname = oldlogname -> next; /* get pointer to next logical name in the table */ else newlogname = lognamtbl -> lognames; /* get first name in table */ if (newlogname != NULL) OZ_HW_ATOMIC_INCBY1_LONG (newlogname -> refcount); /* increment ref count on returned logical name so it can't be deleted */ lognamtbl_unlock (lognamtbl); /* now that ref count is incremented, unlock the table */ if (oldlogname != NULL) oz_knl_logname_increfc (oldlogname, -1); /* decrement ref count on input logical name */ *logname_r = newlogname; return (OZ_SUCCESS); } /************************************************************************/ /* */ /* Get logical's name */ /* */ /* Input: */ /* */ /* logname = logical name pointer */ /* */ /* Output: */ /* */ /* oz_knl_logname_getname = pointer to null terminated name string */ /* */ /************************************************************************/ const char *oz_knl_logname_getname (OZ_Logname *logname) { OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); return (logname -> name); } /************************************************************************/ /* */ /* Get logical's security attributes */ /* */ /* Input: */ /* */ /* logname = logical name pointer */ /* */ /* Output: */ /* */ /* oz_knl_logname_getsecattr = pointer to security attributes */ /* */ /************************************************************************/ OZ_Secattr *oz_knl_logname_getsecattr (OZ_Logname *logname) { OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); oz_knl_secattr_increfc (logname -> secattr, 1); return (logname -> secattr); } /************************************************************************/ /* */ /* Increment logical name reference count */ /* */ /* Input: */ /* */ /* logname = pointer to logical name to change ref count of */ /* inc = value to increment by */ /* */ /* Output: */ /* */ /* oz_knl_logname_increfc = new ref count */ /* if neg, system crashes */ /* */ /* Note: */ /* */ /* Logical name is not automatically deleted when ref count goes zero /* */ /************************************************************************/ Long oz_knl_logname_increfc (OZ_Logname *logname, Long inc) { Long refc; uLong i, sts; OZ_Logname *xlogname; void *object; OZ_KNL_CHKOBJTYPE (logname, OZ_OBJTYPE_LOGNAME); /* Update reference count under hardware smp lock and get the result */ again: do { refc = logname -> refcount; if (refc < 0) oz_crash ("oz_knl_logname_increfc: logical name %s ref count was %d", logname -> name, refc); if (refc + inc <= 0) goto going_le_zero; } while (!oz_hw_atomic_setif_long (&(logname -> refcount), refc + inc, refc)); return (refc + inc); /* Result can not be negative */ going_le_zero: if (refc + inc < 0) oz_crash ("oz_knl_logname_increfc: logical name %s ref count %d+%d", logname -> name, refc, inc); /* If the logical is not in a table, it is to be deleted */ if (logname -> lognamtbl == NULL) { /* If deleting a table, delete all entries in it first */ if (logname -> lognamatr & OZ_LOGNAMATR_TABLE) { while (1) { sts = lognamtbl_lock (logname); /* lock myself */ if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname_increfc: error %u locking table %s", logname -> name); xlogname = logname -> lognames; /* get a logical name in me */ if (xlogname == NULL) break; /* done if none left */ OZ_HW_ATOMIC_INCBY1_LONG (xlogname -> refcount); /* ok, increment its ref count */ logname -> lognames = xlogname -> next; /* remove from table */ xlogname -> lognamtbl = NULL; lognamtbl_unlock (logname); /* unlock the table - we can't do recursive locking */ oz_knl_logname_increfc (xlogname, -1); /* recursive call to decrement ref count */ } lognamtbl_unlock (logname); /* i am empty, unlock myself */ } /* Free off any locking event flag */ if (logname -> tablevent != NULL) { oz_knl_event_increfc (logname -> tablevent, -1); logname -> tablevent = NULL; } /* Free off any security attributes */ if (logname -> secattr != NULL) { oz_knl_secattr_increfc (logname -> secattr, -1); logname -> secattr = NULL; } /* Unlock any referenced objects */ for (i = 0; i < logname -> nvalues; i ++) { if (logname -> values[i].attr & OZ_LOGVALATR_OBJECT) { object = logname -> values[i].buff; sts = oz_knl_logname_incobjrefc (object, -1, NULL); if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname_increfc: error %u decrement object ref count logname %s object %s", sts, logname -> name, logname -> values[i].buff); } } /* Free off memory block */ if (logname -> refcount != refc) { oz_crash ("oz_knl_logname_increfc: %p refcount changed from %d to %d", logname, refc, logname -> refcount); } OZ_KNL_PGPFREE (logname); } /* It's in a table, so just set its refcount to zero and leave it in the table */ else if (!oz_hw_atomic_setif_long (&(logname -> refcount), 0, refc)) goto again; return (0); } /************************************************************************/ /* */ /* Delete logical name */ /* */ /* Input: */ /* */ /* logname = logical name entry to delete */ /* */ /* Output: */ /* */ /* reference count decremented */ /* entry removed from table and marked for delete */ /* */ /************************************************************************/ void oz_knl_logname_delete (OZ_Logname *logname) { uLong sts; OZ_Logname *lognamtbl; /* If logical is in a table, remove it */ lognamtbl = logname -> lognamtbl; if (lognamtbl != NULL) { sts = lognamtbl_lock (lognamtbl); /* lock table */ if (sts != OZ_SUCCESS) oz_crash ("oz_knl_logname_delete: error %u locking table for %s", logname -> name); markdelete (logname); /* remove entry from table */ lognamtbl_unlock (lognamtbl); /* unlock table */ } /* Decrement ref count and free it off */ oz_knl_logname_increfc (logname, -1); } /************************************************************************/ /* */ /* Increment object reference count. Only include objects that can */ /* be incd and decd at will. */ /* */ /* Input: */ /* */ /* object = object pointer */ /* inc = value of increment */ /* */ /* Output: */ /* */ /* oz_knl_logname_incobjrefc = OZ_SUCCESS : successful */ /* else : error status */ /* *objtypstr = object type string */ /* */ /************************************************************************/ uLong oz_knl_logname_incobjrefc (void *object, Long inc, char **objtypstr) { char *ots; switch (OZ_KNL_GETOBJTYPE (object)) { case OZ_OBJTYPE_DEVUNIT: { if (inc != 0) oz_knl_devunit_increfc (object, inc); ots = "devunit"; break; } case OZ_OBJTYPE_EVENT: { if (inc != 0) oz_knl_event_increfc (object, inc); ots = "event"; break; } case OZ_OBJTYPE_IOCHAN: { if (inc != 0) oz_knl_iochan_increfc (object, inc); ots = "iochan"; break; } case OZ_OBJTYPE_JOB: { if (inc != 0) oz_knl_job_increfc (object, inc); ots = "job"; break; } case OZ_OBJTYPE_LOGNAME: { if (inc != 0) oz_knl_logname_increfc (object, inc); ots = "logname"; break; } case OZ_OBJTYPE_PROCESS: { if (inc != 0) oz_knl_process_increfc (object, inc); ots = "process"; break; } case OZ_OBJTYPE_SECTION: { if (inc != 0) oz_knl_section_increfc (object, inc); ots = "section"; break; } case OZ_OBJTYPE_THREAD: { if (inc != 0) oz_knl_thread_increfc (object, inc); ots = "thread"; break; } case OZ_OBJTYPE_USER: { if (inc != 0) oz_knl_user_increfc (object, inc); ots = "user"; break; } default: { oz_knl_printk ("oz_knl_logname_incobjrefc: object %p is type %d\n", object, OZ_KNL_GETOBJTYPE (object)); return (OZ_BADLOGNOBJTYPE); } } if (objtypstr != NULL) *objtypstr = ots; return (OZ_SUCCESS); } /************************************************************************/ /* */ /* Internal Routines */ /* */ /************************************************************************/ /************************************************************************/ /* */ /* This routine converts an alleged table object pointer to a genuine */ /* table object pointer */ /* */ /* Input: */ /* */ /* lognamtbl = object pointer */ /* */ /* Output: */ /* */ /* cvtlognamtblobj = NULL : unrecognised object type */ /* else : pointer to corresponding table */ /* */ /* Note: */ /* */ /* A Thread object converts to the process' directory */ /* A Process object converts to the process' directory */ /* A Job object converts to the job's directory */ /* An User object converts to the user's directory */ /* */ /************************************************************************/ static OZ_Logname *cvtlognamtblobj (OZ_Logname *lognamtbl) { switch (OZ_KNL_GETOBJTYPE (lognamtbl)) { case OZ_OBJTYPE_LOGNAME: { break; } case OZ_OBJTYPE_THREAD: { lognamtbl = oz_knl_thread_getprocess (lognamtbl); } case OZ_OBJTYPE_PROCESS: { lognamtbl = oz_knl_process_getlognamdir (lognamtbl); break; } case OZ_OBJTYPE_JOB: { lognamtbl = oz_knl_job_getlognamdir (lognamtbl); break; } case OZ_OBJTYPE_USER: { lognamtbl = oz_knl_user_getlognamdir (lognamtbl); break; } default: { lognamtbl = NULL; break; } } OZ_KNL_CHKOBJTYPE (lognamtbl, OZ_OBJTYPE_LOGNAME); return (lognamtbl); } /************************************************************************/ /* */ /* Lock logical name table */ /* */ /* No recursive table locks are allowed, a thread may only have one */ /* logical name table locked at a time to avoid deadlocks */ /* */ /************************************************************************/ static uLong lognamtbl_lock (OZ_Logname *lognamtbl) { if (lognamtbl -> tablevent == NULL) return (OZ_NOTLOGNAMTBL); while (oz_knl_event_set (lognamtbl -> tablevent, 0) == 0) { oz_knl_event_waitone (lognamtbl -> tablevent); } return (OZ_SUCCESS); } /************************************************************************/ /* */ /* Unlock logical name table */ /* */ /************************************************************************/ static void lognamtbl_unlock (OZ_Logname *lognamtbl) { oz_knl_event_set (lognamtbl -> tablevent, 1); } /************************************************************************/ /* */ /* Mark a logical name for delete by removing it from its table. */ /* This routine must be called with the table locked. */ /* */ /************************************************************************/ static void markdelete (OZ_Logname *logname) { OZ_Logname **llogname, *xlogname; for (llogname = &(logname -> lognamtbl -> lognames); (xlogname = *llogname) != logname; llogname = &(xlogname -> next)) { if (xlogname == NULL) oz_crash ("oz_knl_logname markdel: can't find logical name %s in table", logname -> name); } *llogname = xlogname -> next; xlogname -> lognamtbl = NULL; } /************************************************************************/ /* */ /* Dump out logical name to console */ /* */ /************************************************************************/ void oz_knl_logname_dump (int level, OZ_Logname *logname) { char tmpbuf[sizeof(OZ_Pointer)*2+32]; int i; uLong sts; OZ_Logname *lnm; for (i = 0; i < level; i ++) oz_knl_printk (" "); oz_knl_printk (" %s", logname -> name); if (logname -> lognamatr & OZ_LOGNAMATR_NOSUPERSEDE) oz_knl_printk (" (nosupersede)"); if (logname -> lognamatr & OZ_LOGNAMATR_NOOUTERMODE) oz_knl_printk (" (nooutermode)"); if (logname -> procmode == OZ_PROCMODE_KNL) oz_knl_printk (" (kernel)"); else if (logname -> procmode == OZ_PROCMODE_USR) oz_knl_printk (" (user)"); else oz_knl_printk (" (%d)", logname -> procmode); oz_knl_printk (" (ref:%d)", logname -> refcount); if (logname -> lognamatr & OZ_LOGNAMATR_TABLE) { oz_knl_printk (" (table)\n"); sts = lognamtbl_lock (logname); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u locking table %s\n", logname -> name); } else { for (lnm = logname -> lognames; lnm != NULL; lnm = lnm -> next) { oz_knl_logname_dump (level + 1, lnm); } lognamtbl_unlock (logname); } } else { oz_knl_printk (" ="); for (i = 0; i < logname -> nvalues; i ++) { if (logname -> values[i].attr & OZ_LOGVALATR_OBJECT) { sts = oz_knl_logname_objstr (logname, i, sizeof tmpbuf, tmpbuf); if (sts != OZ_SUCCESS) oz_sys_sprintf (sizeof tmpbuf, tmpbuf, "err %u", sts); oz_knl_printk (" '%s'", tmpbuf); } else { oz_knl_printk (" '%s'", logname -> values[i].buff); } if (logname -> values[i].attr & OZ_LOGVALATR_OBJECT) oz_knl_printk (" (object)"); if (logname -> values[i].attr & OZ_LOGVALATR_TERMINAL) oz_knl_printk (" (terminal)"); } oz_knl_printk ("\n"); } }