/**Copyright(c)1997,1998DougRabson*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovided
withthedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERR
UPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/subr_bus.c,v1.54.2.82001/01/1800:19:50n_hibmaExp$*/#include"opt_bus.h"#include<sys/param.h>#include<sys/queue.h>#include<sys/malloc.h>#include<sys/kernel.h>#include<sys/module.h>#ifdefDEVICE_SYSCTLS#include<sys/sysctl.h>#
endif#include<sys/bus_private.h>#include<sys/systm.h>#include<machine/bus.h>#include<sys/rman.h>#include<machine/stdarg.h>/*fordevice_printf()*/MALLOC_DEFINE(M_BUS,"bus","Busdatastructures");#ifdefBUS_DEBUG#definePDEBUG(a)(printf(__FUNCTION__":%d:",__LINE__),printfa,printf("\n"))#defineDEVICENAME(d)((d)?device_get_name(d):"nodevice")#defineDRIVERNAME(d)((d)?d->name:"nodriver")#defineDEVCLANAME(d)((d)?d->name:"nodevclass")/*Producetheindenting,ind
ent*2spacesplusa'.'aheadofthatto*preventsyslogfromdeletinginitialspaces*/#defineindentprintf(p)do{intiJ;printf(".");for(iJ=0;iJ<indent;iJ++)printf("");printfp;}while(0)staticvoidprint_method_list(device_method_t*m,intindent);staticvoidprint_device_ops(device_ops_tops,intindent);staticvoidprint_device_short(device_tdev,intindent);staticvoidprint_device(device_tdev,intindent);voidprint_device_tree_short(device_tdev,intindent);voidprint_device_tree(
device_tdev,intindent);staticvoidprint_driver_short(driver_t*driver,intindent);staticvoidprint_driver(driver_t*driver,intindent);staticvoidprint_driver_list(driver_list_tdrivers,intindent);staticvoidprint_devclass_short(devclass_tdc,intindent);staticvoidprint_devclass(devclass_tdc,intindent);voidprint_devclass_list_short(void);voidprint_devclass_list(void);#else/*Makethecompilerignorethefunctioncalls*/#definePDEBUG(a)/*nop*/#defineDEVICENAME(d)/*
nop*/#defineDRIVERNAME(d)/*nop*/#defineDEVCLANAME(d)/*nop*/#defineprint_method_list(m,i)/*nop*/#defineprint_device_ops(o,i)/*nop*/#defineprint_device_short(d,i)/*nop*/#defineprint_device(d,i)/*nop*/#defineprint_device_tree_short(d,i)/*nop*/#defineprint_device_tree(d,i)/*nop*/#defineprint_driver_short(d,i)/*nop*/#defineprint_driver(d,i)/*nop*/#defineprint_driver_list(d,i)/*nop*/#defineprint_devclass_short(d,i)/*nop*/#defineprint_devclass(d,i)/*nop
*/#defineprint_devclass_list_short()/*nop*/#defineprint_devclass_list()/*nop*/#endif#ifdefDEVICE_SYSCTLSstaticvoiddevice_register_oids(device_tdev);staticvoiddevice_unregister_oids(device_tdev);#endif/**Methodtablehandling*/staticinterror_method(void);staticintnext_method_offset=1;LIST_HEAD(methodlist,method)methods;structmethod{LIST_ENTRY(method)link;/*linkedlistofmethods*/intoffset;/*offsetinmethodtable*/intrefs;/*countofdevice_op_descusers*/de
vop_tdeflt;/*defaultimplementation*/char*name;/*uniquenameofmethod*/};staticvoidregister_method(structdevice_op_desc*desc){structmethod*m;if(desc->method){desc->method->refs++;return;}/**Makesurethatdesc->defltisalwaysvalidtosimplifydispatch.*/if(!desc->deflt)desc->deflt=error_method;for(m=LIST_FIRST(&methods);m;m=LIST_NEXT(m,link)){if(!strcmp(m->name,desc->name)){desc->offset=m->offset;desc->method=m;m->refs++;PDEBUG(("method%phasthesamename,%s,
withoffset%d",(void*)m,desc->name,desc->offset));return;}}m=(structmethod*)malloc(sizeof(structmethod)+strlen(desc->name)+1,M_BUS,M_NOWAIT);if(!m)panic("register_method:outofmemory");bzero(m,sizeof(structmethod)+strlen(desc->name)+1);m->offset=next_method_offset++;m->refs=1;m->deflt=desc->deflt;m->name=(char*)(m+1);strcpy(m->name,desc->name);LIST_INSERT_HEAD(&methods,m,link);desc->offset=m->offset;desc->method=m;}staticvoidunregister_method(struc
tdevice_op_desc*desc){structmethod*m=desc->method;m->refs--;if(m->refs==0){PDEBUG(("method%s,reachedrefcount0",desc->name));LIST_REMOVE(m,link);free(m,M_BUS);desc->method=0;}}staticinterror_method(void){returnENXIO;}staticstructdevice_opsnull_ops={1,{error_method}};staticvoidcompile_methods(driver_t*driver){device_ops_tops;structdevice_method*m;structmethod*cm;inti;/**Firstregisteranymethodswhichneedit.*/for(i=0,m=driver->methods;m->desc;i++,m++)
register_method(m->desc);/**Thenallocatethecompiledoptable.*/ops=malloc(sizeof(structdevice_ops)+(next_method_offset-1)*sizeof(devop_t),M_BUS,M_NOWAIT);if(!ops)panic("compile_methods:outofmemory");bzero(ops,sizeof(structdevice_ops)+(next_method_offset-1)*sizeof(devop_t));ops->maxoffset=next_method_offset;/*Fillindefaultmethodsandthenoverwritewithdrivermethods*/for(i=0;i<next_method_offset;i++)ops->methods[i]=error_method;for(cm=LIST_FIRST(&method
s);cm;cm=LIST_NEXT(cm,link)){if(cm->deflt)ops->methods[cm->offset]=cm->deflt;}for(i=0,m=driver->methods;m->desc;i++,m++)ops->methods[m->desc->offset]=m->func;PDEBUG(("%shas%dmethod%s,wasting%dbytes",DRIVERNAME(driver),i,(i==1?"":"s"),(next_method_offset-i)*sizeof(devop_t)));driver->ops=ops;}staticvoidfree_methods(driver_t*driver){inti;structdevice_method*m;/**Unregisteranymethodswhicharenolongerused.*/for(i=0,m=driver->methods;m->desc;i++,m++)unr
egister_method(m->desc);/**Freememoryandcleanup.*/free(driver->ops,M_BUS);driver->ops=0;}/**Devclassimplementation*/staticdevclass_list_tdevclasses=TAILQ_HEAD_INITIALIZER(devclasses);staticdevclass_tdevclass_find_internal(constchar*classname,intcreate){devclass_tdc;PDEBUG(("lookingfor%s",classname));if(!classname)returnNULL;for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))if(!strcmp(dc->name,classname))returndc;PDEBUG(("%snotfound%s",cla
ssname,(create?",creating":"")));if(create){dc=malloc(sizeof(structdevclass)+strlen(classname)+1,M_BUS,M_NOWAIT);if(!dc)returnNULL;bzero(dc,sizeof(structdevclass)+strlen(classname)+1);dc->name=(char*)(dc+1);strcpy(dc->name,classname);dc->devices=NULL;dc->maxunit=0;TAILQ_INIT(&dc->drivers);TAILQ_INSERT_TAIL(&devclasses,dc,link);}returndc;}devclass_tdevclass_create(constchar*classname){returndevclass_find_internal(classname,TRUE);}devclass_tdevclas
s_find(constchar*classname){returndevclass_find_internal(classname,FALSE);}intdevclass_add_driver(devclass_tdc,driver_t*driver){driverlink_tdl;inti;PDEBUG(("%s",DRIVERNAME(driver)));dl=malloc(sizeof*dl,M_BUS,M_NOWAIT);if(!dl)returnENOMEM;bzero(dl,sizeof*dl);/**Compilethedriver'smethods.*/if(!driver->ops)compile_methods(driver);/**Makesurethedevclasswhichthedriverisimplementingexists.*/devclass_find_internal(driver->name,TRUE);dl->driver=driver;TA
ILQ_INSERT_TAIL(&dc->drivers,dl,link);driver->refs++;/**CallBUS_DRIVER_ADDEDforanyexistingbussesinthisclass.*/for(i=0;i<dc->maxunit;i++)if(dc->devices[i])BUS_DRIVER_ADDED(dc->devices[i],driver);return0;}intdevclass_delete_driver(devclass_tbusclass,driver_t*driver){devclass_tdc=devclass_find(driver->name);driverlink_tdl;device_tdev;inti;interror;PDEBUG(("%sfromdevclass%s",driver->name,DEVCLANAME(busclass)));if(!dc)return0;/**Findthelinkstructurein
thebus'listofdrivers.*/for(dl=TAILQ_FIRST(&busclass->drivers);dl;dl=TAILQ_NEXT(dl,link)){if(dl->driver==driver)break;}if(!dl){PDEBUG(("%snotfoundin%slist",driver->name,busclass->name));returnENOENT;}/**Disassociatefromanydevices.Weiteratethroughallthe*devicesinthedevclassofthedriveranddetachanywhichare*usingthedriverandwhichhaveaparentinthedevclasswhich*wearedeletingfrom.**Notethatsinceadrivercanbeinmultipledevclasses,we*shouldnotdetachdeviceswhi
charenotchildrenofdevicesin*theaffecteddevclass.*/for(i=0;i<dc->maxunit;i++){if(dc->devices[i]){dev=dc->devices[i];if(dev->driver==driver&&dev->parent&&dev->parent->devclass==busclass){if((error=device_detach(dev))!=0)returnerror;device_set_driver(dev,NULL);}}}TAILQ_REMOVE(&busclass->drivers,dl,link);free(dl,M_BUS);driver->refs--;if(driver->refs==0)free_methods(driver);return0;}staticdriverlink_tdevclass_find_driver_internal(devclass_tdc,constcha
r*classname){driverlink_tdl;PDEBUG(("%sindevclass%s",classname,DEVCLANAME(dc)));for(dl=TAILQ_FIRST(&dc->drivers);dl;dl=TAILQ_NEXT(dl,link)){if(!strcmp(dl->driver->name,classname))returndl;}PDEBUG(("notfound"));returnNULL;}driver_t*devclass_find_driver(devclass_tdc,constchar*classname){driverlink_tdl;dl=devclass_find_driver_internal(dc,classname);if(dl)returndl->driver;elsereturnNULL;}constchar*devclass_get_name(devclass_tdc){returndc->name;}devic
e_tdevclass_get_device(devclass_tdc,intunit){if(dc==NULL||unit<0||unit>=dc->maxunit)returnNULL;returndc->devices[unit];}void*devclass_get_softc(devclass_tdc,intunit){device_tdev;dev=devclass_get_device(dc,unit);if(!dev)return(NULL);return(device_get_softc(dev));}intdevclass_get_devices(devclass_tdc,device_t**devlistp,int*devcountp){inti;intcount;device_t*list;count=0;for(i=0;i<dc->maxunit;i++)if(dc->devices[i])count++;list=malloc(count*sizeof(dev
ice_t),M_TEMP,M_NOWAIT);if(!list)returnENOMEM;bzero(list,count*sizeof(device_t));count=0;for(i=0;i<dc->maxunit;i++)if(dc->devices[i]){list[count]=dc->devices[i];count++;}*devlistp=list;*devcountp=count;return0;}intdevclass_get_maxunit(devclass_tdc){returndc->maxunit;}staticintdevclass_alloc_unit(devclass_tdc,int*unitp){intunit=*unitp;PDEBUG(("unit%dindevclass%s",unit,DEVCLANAME(dc)));/*Ifwehavebeengivenawiredunitnumber,checkforexistingdevice*/if(
unit!=-1){if(unit>=0&&unit<dc->maxunit&&dc->devices[unit]!=NULL){if(bootverbose)printf("%s-:%s%dexists,usingnextavailableunitnumber\n",dc->name,dc->name,unit);/*findthenextavailableslot*/while(++unit<dc->maxunit&&dc->devices[unit]!=NULL);}}else{/*Unwireddevice,findthenextavailableslotforit*/unit=0;while(unit<dc->maxunit&&dc->devices[unit]!=NULL)unit++;}/**We'veselectedaunitbeyondthelengthofthetable,solet'sextend*thetabletomakeroomforallunitsuptoa
ndincludingthisone.*/if(unit>=dc->maxunit){device_t*newlist;intnewsize;newsize=roundup((unit+1),MINALLOCSIZE/sizeof(device_t));newlist=malloc(sizeof(device_t)*newsize,M_BUS,M_NOWAIT);if(!newlist)returnENOMEM;bcopy(dc->devices,newlist,sizeof(device_t)*dc->maxunit);bzero(newlist+dc->maxunit,sizeof(device_t)*(newsize-dc->maxunit));if(dc->devices)free(dc->devices,M_BUS);dc->devices=newlist;dc->maxunit=newsize;}PDEBUG(("now:unit%dindevclass%s",unit,DE
VCLANAME(dc)));*unitp=unit;return0;}staticintdevclass_add_device(devclass_tdc,device_tdev){intbuflen,error;PDEBUG(("%sindevclass%s",DEVICENAME(dev),DEVCLANAME(dc)));buflen=strlen(dc->name)+5;dev->nameunit=malloc(buflen,M_BUS,M_NOWAIT);if(!dev->nameunit)returnENOMEM;bzero(dev->nameunit,buflen);if((error=devclass_alloc_unit(dc,&dev->unit))!=0){free(dev->nameunit,M_BUS);dev->nameunit=NULL;returnerror;}dc->devices[dev->unit]=dev;dev->devclass=dc;snpr
intf(dev->nameunit,buflen,"%s%d",dc->name,dev->unit);#ifdefDEVICE_SYSCTLSdevice_register_oids(dev);#endifreturn0;}staticintdevclass_delete_device(devclass_tdc,device_tdev){if(!dc||!dev)return0;PDEBUG(("%sindevclass%s",DEVICENAME(dev),DEVCLANAME(dc)));if(dev->devclass!=dc||dc->devices[dev->unit]!=dev)panic("devclass_delete_device:inconsistentdeviceclass");dc->devices[dev->unit]=NULL;if(dev->flags&DF_WILDCARD)dev->unit=-1;dev->devclass=NULL;free(de
v->nameunit,M_BUS);dev->nameunit=NULL;#ifdefDEVICE_SYSCTLSdevice_unregister_oids(dev);#endifreturn0;}staticdevice_tmake_device(device_tparent,constchar*name,intunit){device_tdev;devclass_tdc;PDEBUG(("%sat%sasunit%d",name,DEVICENAME(parent),unit));if(name){dc=devclass_find_internal(name,TRUE);if(!dc){printf("make_device:can'tfinddeviceclass%s\n",name);returnNULL;}}elsedc=NULL;dev=malloc(sizeof(structdevice),M_BUS,M_NOWAIT);if(!dev)return0;bzero(de
v,sizeof(structdevice));dev->parent=parent;TAILQ_INIT(&dev->children);dev->ops=&null_ops;dev->driver=NULL;dev->devclass=NULL;dev->unit=unit;dev->nameunit=NULL;dev->desc=NULL;dev->busy=0;dev->devflags=0;dev->flags=DF_ENABLED;dev->order=0;if(unit==-1)dev->flags|=DF_WILDCARD;if(name){dev->flags|=DF_FIXEDCLASS;devclass_add_device(dc,dev);}dev->ivars=NULL;dev->softc=NULL;dev->state=DS_NOTPRESENT;returndev;}staticintdevice_print_child(device_tdev,devic
e_tchild){intretval=0;if(device_is_alive(child)){retval+=BUS_PRINT_CHILD(dev,child);}elseretval+=device_printf(child,"notfound\n");return(retval);}device_tdevice_add_child(device_tdev,constchar*name,intunit){returndevice_add_child_ordered(dev,0,name,unit);}device_tdevice_add_child_ordered(device_tdev,intorder,constchar*name,intunit){device_tchild;device_tplace;PDEBUG(("%sat%swithorder%dasunit%d",name,DEVICENAME(dev),order,unit));child=make_device
(dev,name,unit);if(child==NULL)returnchild;child->order=order;TAILQ_FOREACH(place,&dev->children,link)if(place->order>order)break;if(place){/**Thedevice'place'isthefirstdevicewhoseorderis*greaterthanthenewchild.*/TAILQ_INSERT_BEFORE(place,child,link);}else{/**Thenewchild'sorderisgreaterorequaltotheorderof*anyexistingdevice.Addthechildtothetailofthelist.*/TAILQ_INSERT_TAIL(&dev->children,child,link);}returnchild;}intdevice_delete_child(device_tdev
,device_tchild){interror;device_tgrandchild;PDEBUG(("%sfrom%s",DEVICENAME(child),DEVICENAME(dev)));/*removechildrenfirst*/while((grandchild=TAILQ_FIRST(&child->children))){error=device_delete_child(child,grandchild);if(error)returnerror;}if((error=device_detach(child))!=0)returnerror;if(child->devclass)devclass_delete_device(child->devclass,child);TAILQ_REMOVE(&dev->children,child,link);device_set_desc(child,NULL);free(child,M_BUS);return0;}/**Fi
ndonlydevicesattachedtothisbus.*/device_tdevice_find_child(device_tdev,constchar*classname,intunit){devclass_tdc;device_tchild;dc=devclass_find(classname);if(!dc)returnNULL;child=devclass_get_device(dc,unit);if(child&&child->parent==dev)returnchild;returnNULL;}staticdriverlink_tfirst_matching_driver(devclass_tdc,device_tdev){if(dev->devclass)returndevclass_find_driver_internal(dc,dev->devclass->name);elsereturnTAILQ_FIRST(&dc->drivers);}staticdri
verlink_tnext_matching_driver(devclass_tdc,device_tdev,driverlink_tlast){if(dev->devclass){driverlink_tdl;for(dl=TAILQ_NEXT(last,link);dl;dl=TAILQ_NEXT(dl,link))if(!strcmp(dev->devclass->name,dl->driver->name))returndl;returnNULL;}elsereturnTAILQ_NEXT(last,link);}staticintdevice_probe_child(device_tdev,device_tchild){devclass_tdc;driverlink_tbest=0;driverlink_tdl;intresult,pri=0;inthasclass=(child->devclass!=0);dc=dev->devclass;if(!dc)panic("devi
ce_probe_child:parentdevicehasnodevclass");if(child->state==DS_ALIVE)return0;for(dl=first_matching_driver(dc,child);dl;dl=next_matching_driver(dc,child,dl)){PDEBUG(("Trying%s",DRIVERNAME(dl->driver)));device_set_driver(child,dl->driver);if(!hasclass)device_set_devclass(child,dl->driver->name);result=DEVICE_PROBE(child);if(!hasclass)device_set_devclass(child,0);/**IfthedriverreturnsSUCCESS,therecanbenohighermatch*forthisdevice.*/if(result==0){best
=dl;pri=0;break;}/**Thedriverreturnedanerrorsoitcertainlydoesn'tmatch.*/if(result>0){device_set_driver(child,0);continue;}/**AprioritylowerthanSUCCESS,rememberthebestmatching*driver.Initialisethevalueofpriforthefirstmatch.*/if(best==0||result>pri){best=dl;pri=result;continue;}}/**Ifwefoundadriver,changestateandinitialisethedevclass.*/if(best){if(!child->devclass)device_set_devclass(child,best->driver->name);device_set_driver(child,best->driver);i
f(pri<0){/**Abitbogus.Calltheprobemethodagaintomakesure*thatwehavetherightdescription.*/DEVICE_PROBE(child);}child->state=DS_ALIVE;return0;}returnENXIO;}device_tdevice_get_parent(device_tdev){returndev->parent;}intdevice_get_children(device_tdev,device_t**devlistp,int*devcountp){intcount;device_tchild;device_t*list;count=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))count++;list=malloc(count*sizeof(device_t),M_TEMP,M_
NOWAIT);if(!list)returnENOMEM;bzero(list,count*sizeof(device_t));count=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){list[count]=child;count++;}*devlistp=list;*devcountp=count;return0;}driver_t*device_get_driver(device_tdev){returndev->driver;}devclass_tdevice_get_devclass(device_tdev){returndev->devclass;}constchar*device_get_name(device_tdev){if(dev->devclass)returndevclass_get_name(dev->devclass);returnNULL;}const
char*device_get_nameunit(device_tdev){returndev->nameunit;}intdevice_get_unit(device_tdev){returndev->unit;}constchar*device_get_desc(device_tdev){returndev->desc;}u_int32_tdevice_get_flags(device_tdev){returndev->devflags;}intdevice_print_prettyname(device_tdev){constchar*name=device_get_name(dev);if(name==0)returnprintf("unknown:");elsereturnprintf("%s%d:",name,device_get_unit(dev));}intdevice_printf(device_tdev,constchar*fmt,...){va_listap;int
retval;retval=device_print_prettyname(dev);va_start(ap,fmt);retval+=vprintf(fmt,ap);va_end(ap);returnretval;}staticvoiddevice_set_desc_internal(device_tdev,constchar*desc,intcopy){if(dev->desc&&(dev->flags&DF_DESCMALLOCED)){free(dev->desc,M_BUS);dev->flags&=~DF_DESCMALLOCED;dev->desc=NULL;}if(copy&&desc){dev->desc=malloc(strlen(desc)+1,M_BUS,M_NOWAIT);if(dev->desc){strcpy(dev->desc,desc);dev->flags|=DF_DESCMALLOCED;}}else/*Avoida-Wcast-qualwarnin
g*/dev->desc=(char*)(uintptr_t)desc;#ifdefDEVICE_SYSCTLS{structsysctl_oid*oid=&dev->oid[1];oid->oid_arg1=dev->desc?dev->desc:"";oid->oid_arg2=dev->desc?strlen(dev->desc):0;}#endif}voiddevice_set_desc(device_tdev,constchar*desc){device_set_desc_internal(dev,desc,FALSE);}voiddevice_set_desc_copy(device_tdev,constchar*desc){device_set_desc_internal(dev,desc,TRUE);}voiddevice_set_flags(device_tdev,u_int32_tflags){dev->devflags=flags;}void*device_get_
softc(device_tdev){returndev->softc;}voiddevice_set_softc(device_tdev,void*softc){if(dev->softc&&!(dev->flags&DF_EXTERNALSOFTC))free(dev->softc,M_BUS);dev->softc=softc;if(dev->softc)dev->flags|=DF_EXTERNALSOFTC;elsedev->flags&=~DF_EXTERNALSOFTC;}void*device_get_ivars(device_tdev){returndev->ivars;}voiddevice_set_ivars(device_tdev,void*ivars){if(!dev)return;dev->ivars=ivars;return;}device_state_tdevice_get_state(device_tdev){returndev->state;}void
device_enable(device_tdev){dev->flags|=DF_ENABLED;}voiddevice_disable(device_tdev){dev->flags&=~DF_ENABLED;}voiddevice_busy(device_tdev){if(dev->state<DS_ATTACHED)panic("device_busy:calledforunattacheddevice");if(dev->busy==0&&dev->parent)device_busy(dev->parent);dev->busy++;dev->state=DS_BUSY;}voiddevice_unbusy(device_tdev){if(dev->state!=DS_BUSY)panic("device_unbusy:calledfornon-busydevice");dev->busy--;if(dev->busy==0){if(dev->parent)device_un
busy(dev->parent);dev->state=DS_ATTACHED;}}voiddevice_quiet(device_tdev){dev->flags|=DF_QUIET;}voiddevice_verbose(device_tdev){dev->flags&=~DF_QUIET;}intdevice_is_quiet(device_tdev){return(dev->flags&DF_QUIET)!=0;}intdevice_is_enabled(device_tdev){return(dev->flags&DF_ENABLED)!=0;}intdevice_is_alive(device_tdev){returndev->state>=DS_ALIVE;}intdevice_set_devclass(device_tdev,constchar*classname){devclass_tdc;if(!classname){if(dev->devclass)devclas
s_delete_device(dev->devclass,dev);return0;}if(dev->devclass){printf("device_set_devclass:deviceclassalreadyset\n");returnEINVAL;}dc=devclass_find_internal(classname,TRUE);if(!dc)returnENOMEM;returndevclass_add_device(dc,dev);}intdevice_set_driver(device_tdev,driver_t*driver){if(dev->state>=DS_ATTACHED)returnEBUSY;if(dev->driver==driver)return0;if(dev->softc&&!(dev->flags&DF_EXTERNALSOFTC)){free(dev->softc,M_BUS);dev->softc=NULL;}dev->ops=&null_o
ps;dev->driver=driver;if(driver){dev->ops=driver->ops;if(!(dev->flags&DF_EXTERNALSOFTC)){dev->softc=malloc(driver->softc,M_BUS,M_NOWAIT);if(!dev->softc){dev->ops=&null_ops;dev->driver=NULL;returnENOMEM;}bzero(dev->softc,driver->softc);}}return0;}intdevice_probe_and_attach(device_tdev){device_tbus=dev->parent;interror=0;inthasclass=(dev->devclass!=0);if(dev->state>=DS_ALIVE)return0;if(dev->flags&DF_ENABLED){error=device_probe_child(bus,dev);if(!er
ror){if(!device_is_quiet(dev))device_print_child(bus,dev);error=DEVICE_ATTACH(dev);if(!error)dev->state=DS_ATTACHED;else{printf("device_probe_and_attach:%s%dattachreturned%d\n",dev->driver->name,dev->unit,error);/*Unsettheclassthatwassetindevice_probe_child*/if(!hasclass)device_set_devclass(dev,0);device_set_driver(dev,NULL);dev->state=DS_NOTPRESENT;}}else{if(!(dev->flags&DF_DONENOMATCH)){BUS_PROBE_NOMATCH(bus,dev);dev->flags|=DF_DONENOMATCH;}}}e
lse{if(bootverbose){device_print_prettyname(dev);printf("notprobed(disabled)\n");}}returnerror;}intdevice_detach(device_tdev){interror;PDEBUG(("%s",DEVICENAME(dev)));if(dev->state==DS_BUSY)returnEBUSY;if(dev->state!=DS_ATTACHED)return0;if((error=DEVICE_DETACH(dev))!=0)returnerror;device_printf(dev,"detached\n");if(dev->parent)BUS_CHILD_DETACHED(dev->parent,dev);if(!(dev->flags&DF_FIXEDCLASS))devclass_delete_device(dev->devclass,dev);dev->state=DS
_NOTPRESENT;device_set_driver(dev,NULL);return0;}intdevice_shutdown(device_tdev){if(dev->state<DS_ATTACHED)return0;returnDEVICE_SHUTDOWN(dev);}intdevice_set_unit(device_tdev,intunit){devclass_tdc;interr;dc=device_get_devclass(dev);if(unit<dc->maxunit&&dc->devices[unit])returnEBUSY;err=devclass_delete_device(dc,dev);if(err)returnerr;dev->unit=unit;err=devclass_add_device(dc,dev);if(err)returnerr;return0;}#ifdefDEVICE_SYSCTLS/**Sysctlnodesfordevice
s.*/SYSCTL_NODE(_hw,OID_AUTO,devices,CTLFLAG_RW,0,"Alistofalldevices");staticintsysctl_handle_children(SYSCTL_HANDLER_ARGS){device_tdev=arg1;device_tchild;intfirst=1,error=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){if(child->nameunit){if(!first){error=SYSCTL_OUT(req,",",1);if(error)returnerror;}else{first=0;}error=SYSCTL_OUT(req,child->nameunit,strlen(child->nameunit));if(error)returnerror;}}error=SYSCTL_OUT(req,"
",1);returnerror;}staticintsysctl_handle_state(SYSCTL_HANDLER_ARGS){device_tdev=arg1;switch(dev->state){caseDS_NOTPRESENT:returnSYSCTL_OUT(req,"notpresent",sizeof("notpresent"));caseDS_ALIVE:returnSYSCTL_OUT(req,"alive",sizeof("alive"));caseDS_ATTACHED:returnSYSCTL_OUT(req,"attached",sizeof("attached"));caseDS_BUSY:returnSYSCTL_OUT(req,"busy",sizeof("busy"));}return0;}staticvoiddevice_register_oids(device_tdev){structsysctl_oid*oid;oid=&dev->oid[
0];bzero(oid,sizeof(*oid));oid->oid_parent=&sysctl__hw_devices_children;oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_NODE|CTLFLAG_RW;oid->oid_arg1=&dev->oidlist[0];oid->oid_arg2=0;oid->oid_name=dev->nameunit;oid->oid_handler=0;oid->oid_fmt="N";SLIST_INIT(&dev->oidlist[0]);sysctl_register_oid(oid);oid=&dev->oid[1];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_STRING|CTLFLAG_RD;oid->oid_ar
g1=dev->desc?dev->desc:"";oid->oid_arg2=dev->desc?strlen(dev->desc):0;oid->oid_name="desc";oid->oid_handler=sysctl_handle_string;oid->oid_fmt="A";sysctl_register_oid(oid);oid=&dev->oid[2];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_INT|CTLFLAG_RD;oid->oid_arg1=dev;oid->oid_arg2=0;oid->oid_name="children";oid->oid_handler=sysctl_handle_children;oid->oid_fmt="A";sysctl_register_oid(oid);oi
d=&dev->oid[3];bzero(oid,sizeof(*oid));oid->oid_parent=&dev->oidlist[0];oid->oid_number=OID_AUTO;oid->oid_kind=CTLTYPE_INT|CTLFLAG_RD;oid->oid_arg1=dev;oid->oid_arg2=0;oid->oid_name="state";oid->oid_handler=sysctl_handle_state;oid->oid_fmt="A";sysctl_register_oid(oid);}staticvoiddevice_unregister_oids(device_tdev){sysctl_unregister_oid(&dev->oid[0]);sysctl_unregister_oid(&dev->oid[1]);sysctl_unregister_oid(&dev->oid[2]);}#endif/*=================
=====================*//**Accessfunctionsfordeviceresources.*//*Suppliedbyconfig(8)inioconf.c*/externstructconfig_deviceconfig_devtab[];externintdevtab_count;/*Runtimeversion*/structconfig_device*devtab=config_devtab;staticintresource_new_name(constchar*name,intunit){structconfig_device*new;new=malloc((devtab_count+1)*sizeof(*new),M_TEMP,M_NOWAIT);if(new==NULL)return-1;if(devtab&&devtab_count>0)bcopy(devtab,new,devtab_count*sizeof(*new));bzero(&n
ew[devtab_count],sizeof(*new));new[devtab_count].name=malloc(strlen(name)+1,M_TEMP,M_NOWAIT);if(new[devtab_count].name==NULL){free(new,M_TEMP);return-1;}strcpy(new[devtab_count].name,name);new[devtab_count].unit=unit;new[devtab_count].resource_count=0;new[devtab_count].resources=NULL;devtab=new;returndevtab_count++;}staticintresource_new_resname(intj,constchar*resname,resource_typetype){structconfig_resource*new;inti;i=devtab[j].resource_count;ne
w=malloc((i+1)*sizeof(*new),M_TEMP,M_NOWAIT);if(new==NULL)return-1;if(devtab[j].resources&&i>0)bcopy(devtab[j].resources,new,i*sizeof(*new));bzero(&new[i],sizeof(*new));new[i].name=malloc(strlen(resname)+1,M_TEMP,M_NOWAIT);if(new[i].name==NULL){free(new,M_TEMP);return-1;}strcpy(new[i].name,resname);new[i].type=type;if(devtab[j].resources)free(devtab[j].resources,M_TEMP);devtab[j].resources=new;devtab[j].resource_count=i+1;returni;}staticintresour
ce_match_string(inti,constchar*resname,constchar*value){intj;structconfig_resource*res;for(j=0,res=devtab[i].resources;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->name,resname)&&res->type==RES_STRING&&!strcmp(res->u.stringval,value))returnj;return-1;}staticintresource_find(constchar*name,intunit,constchar*resname,structconfig_resource**result){inti,j;structconfig_resource*res;/**Firstcheckspecificinstances,thengeneric.*/for(i=0;i<devtab_
count;i++){if(devtab[i].unit<0)continue;if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;for(j=0;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->name,resname)){*result=res;return0;}}}for(i=0;i<devtab_count;i++){if(devtab[i].unit>=0)continue;/*XXXshouldthis`&&devtab[i].unit==unit'behere?*//*XXXifso,thenthegenericmatchdoesnothing*/if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;for(j
=0;j<devtab[i].resource_count;j++,res++)if(!strcmp(res->name,resname)){*result=res;return0;}}}returnENOENT;}intresource_int_value(constchar*name,intunit,constchar*resname,int*result){interror;structconfig_resource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_INT)returnEFTYPE;*result=res->u.intval;return0;}intresource_long_value(constchar*name,intunit,constchar*resname,long*result){interror;structconfig_res
ource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_LONG)returnEFTYPE;*result=res->u.longval;return0;}intresource_string_value(constchar*name,intunit,constchar*resname,char**result){interror;structconfig_resource*res;if((error=resource_find(name,unit,resname,&res))!=0)returnerror;if(res->type!=RES_STRING)returnEFTYPE;*result=res->u.stringval;return0;}intresource_query_string(inti,constchar*resname,constchar
*value){if(i<0)i=0;elsei=i+1;for(;i<devtab_count;i++)if(resource_match_string(i,resname,value)>=0)returni;return-1;}intresource_locate(inti,constchar*resname){if(i<0)i=0;elsei=i+1;for(;i<devtab_count;i++)if(!strcmp(devtab[i].name,resname))returni;return-1;}intresource_count(void){returndevtab_count;}char*resource_query_name(inti){returndevtab[i].name;}intresource_query_unit(inti){returndevtab[i].unit;}staticintresource_create(constchar*name,intun
it,constchar*resname,resource_typetype,structconfig_resource**result){inti,j;structconfig_resource*res=NULL;for(i=0;i<devtab_count;i++){if(!strcmp(devtab[i].name,name)&&devtab[i].unit==unit){res=devtab[i].resources;break;}}if(res==NULL){i=resource_new_name(name,unit);if(i<0)returnENOMEM;res=devtab[i].resources;}for(j=0;j<devtab[i].resource_count;j++,res++){if(!strcmp(res->name,resname)){*result=res;return0;}}j=resource_new_resname(i,resname,type)
;if(j<0)returnENOMEM;res=&devtab[i].resources[j];*result=res;return0;}intresource_set_int(constchar*name,intunit,constchar*resname,intvalue){interror;structconfig_resource*res;error=resource_create(name,unit,resname,RES_INT,&res);if(error)returnerror;if(res->type!=RES_INT)returnEFTYPE;res->u.intval=value;return0;}intresource_set_long(constchar*name,intunit,constchar*resname,longvalue){interror;structconfig_resource*res;error=resource_create(name,
unit,resname,RES_LONG,&res);if(error)returnerror;if(res->type!=RES_LONG)returnEFTYPE;res->u.longval=value;return0;}intresource_set_string(constchar*name,intunit,constchar*resname,constchar*value){interror;structconfig_resource*res;error=resource_create(name,unit,resname,RES_STRING,&res);if(error)returnerror;if(res->type!=RES_STRING)returnEFTYPE;if(res->u.stringval)free(res->u.stringval,M_TEMP);res->u.stringval=malloc(strlen(value)+1,M_TEMP,M_NOWA
IT);if(res->u.stringval==NULL)returnENOMEM;strcpy(res->u.stringval,value);return0;}staticvoidresource_cfgload(void*dummy__unused){structconfig_resource*res,*cfgres;inti,j;interror;char*name,*resname;intunit;resource_typetype;char*stringval;intconfig_devtab_count;config_devtab_count=devtab_count;devtab=NULL;devtab_count=0;for(i=0;i<config_devtab_count;i++){name=config_devtab[i].name;unit=config_devtab[i].unit;for(j=0;j<config_devtab[i].resource_co
unt;j++){cfgres=config_devtab[i].resources;resname=cfgres[j].name;type=cfgres[j].type;error=resource_create(name,unit,resname,type,&res);if(error){printf("createresource%s%d:error%d\n",name,unit,error);continue;}if(res->type!=type){printf("typemismatch%s%d:%d!=%d\n",name,unit,res->type,type);continue;}switch(type){caseRES_INT:res->u.intval=cfgres[j].u.intval;break;caseRES_LONG:res->u.longval=cfgres[j].u.longval;break;caseRES_STRING:if(res->u.stri
ngval)free(res->u.stringval,M_TEMP);stringval=cfgres[j].u.stringval;res->u.stringval=malloc(strlen(stringval)+1,M_TEMP,M_NOWAIT);if(res->u.stringval==NULL)break;strcpy(res->u.stringval,stringval);break;default:panic("unknownresourcetype%d\n",type);}}}}SYSINIT(cfgload,SI_SUB_KMEM,SI_ORDER_ANY+50,resource_cfgload,0)/*======================================*//**Someusefulmethodimplementationstomakelifeeasierforbusdrivers.*/voidresource_list_init(stru
ctresource_list*rl){SLIST_INIT(rl);}voidresource_list_free(structresource_list*rl){structresource_list_entry*rle;while((rle=SLIST_FIRST(rl))!=NULL){if(rle->res)panic("resource_list_free:resourceentryisbusy");SLIST_REMOVE_HEAD(rl,link);free(rle,M_BUS);}}voidresource_list_add(structresource_list*rl,inttype,intrid,u_longstart,u_longend,u_longcount){structresource_list_entry*rle;rle=resource_list_find(rl,type,rid);if(!rle){rle=malloc(sizeof(structres
ource_list_entry),M_BUS,M_NOWAIT);if(!rle)panic("resource_list_add:can'trecordentry");SLIST_INSERT_HEAD(rl,rle,link);rle->type=type;rle->rid=rid;rle->res=NULL;}if(rle->res)panic("resource_list_add:resourceentryisbusy");rle->start=start;rle->end=end;rle->count=count;}structresource_list_entry*resource_list_find(structresource_list*rl,inttype,intrid){structresource_list_entry*rle;SLIST_FOREACH(rle,rl,link)if(rle->type==type&&rle->rid==rid)returnrle
;returnNULL;}voidresource_list_delete(structresource_list*rl,inttype,intrid){structresource_list_entry*rle=resource_list_find(rl,type,rid);if(rle){SLIST_REMOVE(rl,rle,resource_list_entry,link);free(rle,M_BUS);}}structresource*resource_list_alloc(structresource_list*rl,device_tbus,device_tchild,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){structresource_list_entry*rle=0;intpassthrough=(device_get_parent(child)!=bus);intisdefault=(
start==0UL&&end==~0UL);if(passthrough){returnBUS_ALLOC_RESOURCE(device_get_parent(bus),child,type,rid,start,end,count,flags);}rle=resource_list_find(rl,type,*rid);if(!rle)return0;/*noresourceofthattype/rid*/if(rle->res)panic("resource_list_alloc:resourceentryisbusy");if(isdefault){start=rle->start;count=max(count,rle->count);end=max(rle->end,start+count-1);}rle->res=BUS_ALLOC_RESOURCE(device_get_parent(bus),child,type,rid,start,end,count,flags);/
**Recordthenewrange.*/if(rle->res){rle->start=rman_get_start(rle->res);rle->end=rman_get_end(rle->res);rle->count=count;}returnrle->res;}intresource_list_release(structresource_list*rl,device_tbus,device_tchild,inttype,intrid,structresource*res){structresource_list_entry*rle=0;intpassthrough=(device_get_parent(child)!=bus);interror;if(passthrough){returnBUS_RELEASE_RESOURCE(device_get_parent(bus),child,type,rid,res);}rle=resource_list_find(rl,typ
e,rid);if(!rle)panic("resource_list_release:can'tfindresource");if(!rle->res)panic("resource_list_release:resourceentryisnotbusy");error=BUS_RELEASE_RESOURCE(device_get_parent(bus),child,type,rid,res);if(error)returnerror;rle->res=NULL;return0;}/**CallDEVICE_IDENTIFYforeachdriver.*/intbus_generic_probe(device_tdev){devclass_tdc=dev->devclass;driverlink_tdl;for(dl=TAILQ_FIRST(&dc->drivers);dl;dl=TAILQ_NEXT(dl,link))DEVICE_IDENTIFY(dl->driver,dev);
return0;}intbus_generic_attach(device_tdev){device_tchild;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))device_probe_and_attach(child);return0;}intbus_generic_detach(device_tdev){device_tchild;interror;if(dev->state!=DS_ATTACHED)returnEBUSY;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))if((error=device_detach(child))!=0)returnerror;return0;}intbus_generic_shutdown(device_tdev){device_tchild;fo
r(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))device_shutdown(child);return0;}intbus_generic_suspend(device_tdev){interror;device_tchild,child2;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){error=DEVICE_SUSPEND(child);if(error){for(child2=TAILQ_FIRST(&dev->children);child2&&child2!=child;child2=TAILQ_NEXT(child2,link))DEVICE_RESUME(child2);return(error);}}return0;}intbus_generic_resume(device_t
dev){device_tchild;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){DEVICE_RESUME(child);/*ifresumefails,there'snothingwecanusefullydo...*/}return0;}intbus_print_child_header(device_tdev,device_tchild){intretval=0;if(device_get_desc(child)){retval+=device_printf(child,"<%s>",device_get_desc(child));}else{retval+=printf("%s",device_get_nameunit(child));}return(retval);}intbus_print_child_footer(device_tdev,device_tchild){r
eturn(printf("on%s\n",device_get_nameunit(dev)));}intbus_generic_print_child(device_tdev,device_tchild){intretval=0;retval+=bus_print_child_header(dev,child);retval+=bus_print_child_footer(dev,child);return(retval);}intbus_generic_read_ivar(device_tdev,device_tchild,intindex,uintptr_t*result){returnENOENT;}intbus_generic_write_ivar(device_tdev,device_tchild,intindex,uintptr_tvalue){returnENOENT;}voidbus_generic_driver_added(device_tdev,driver_t*d
river){device_tchild;DEVICE_IDENTIFY(driver,dev);for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))if(child->state==DS_NOTPRESENT)device_probe_and_attach(child);}intbus_generic_setup_intr(device_tdev,device_tchild,structresource*irq,intflags,driver_intr_t*intr,void*arg,void**cookiep){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_SETUP_INTR(dev->parent,child,irq,flags,intr,arg,cookiep));elsere
turn(EINVAL);}intbus_generic_teardown_intr(device_tdev,device_tchild,structresource*irq,void*cookie){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_TEARDOWN_INTR(dev->parent,child,irq,cookie));elsereturn(EINVAL);}structresource*bus_generic_alloc_resource(device_tdev,device_tchild,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BU
S_ALLOC_RESOURCE(dev->parent,child,type,rid,start,end,count,flags));elsereturn(NULL);}intbus_generic_release_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_RELEASE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}intbus_generic_activate_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupthebushierarchyuntilso
meonehandlesit.*/if(dev->parent)return(BUS_ACTIVATE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}intbus_generic_deactivate_resource(device_tdev,device_tchild,inttype,intrid,structresource*r){/*Propagateupthebushierarchyuntilsomeonehandlesit.*/if(dev->parent)return(BUS_DEACTIVATE_RESOURCE(dev->parent,child,type,rid,r));elsereturn(EINVAL);}/**Someconveniencefunctionstomakeiteasierfordriverstousethe*resource-managementfunctions.Allthe
sereallydoishidethe*indirectionthroughtheparent'smethodtable,makingforslightly*less-wordycode.Inthefuture,itmightmakesenseforthiscode*tomaintainsomesortofalistofresourcesallocatedbyeachdevice.*/structresource*bus_alloc_resource(device_tdev,inttype,int*rid,u_longstart,u_longend,u_longcount,u_intflags){if(dev->parent==0)return(0);return(BUS_ALLOC_RESOURCE(dev->parent,dev,type,rid,start,end,count,flags));}intbus_activate_resource(device_tdev,inttype
,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS_ACTIVATE_RESOURCE(dev->parent,dev,type,rid,r));}intbus_deactivate_resource(device_tdev,inttype,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS_DEACTIVATE_RESOURCE(dev->parent,dev,type,rid,r));}intbus_release_resource(device_tdev,inttype,intrid,structresource*r){if(dev->parent==0)return(EINVAL);return(BUS_RELEASE_RESOURCE(dev->parent,dev,type,rid,r));}intbus
_setup_intr(device_tdev,structresource*r,intflags,driver_intr_thandler,void*arg,void**cookiep){if(dev->parent==0)return(EINVAL);return(BUS_SETUP_INTR(dev->parent,dev,r,flags,handler,arg,cookiep));}intbus_teardown_intr(device_tdev,structresource*r,void*cookie){if(dev->parent==0)return(EINVAL);return(BUS_TEARDOWN_INTR(dev->parent,dev,r,cookie));}intbus_set_resource(device_tdev,inttype,intrid,u_longstart,u_longcount){returnBUS_SET_RESOURCE(device_ge
t_parent(dev),dev,type,rid,start,count);}intbus_get_resource(device_tdev,inttype,intrid,u_long*startp,u_long*countp){returnBUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,startp,countp);}u_longbus_get_resource_start(device_tdev,inttype,intrid){u_longstart,count;interror;error=BUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,&start,&count);if(error)return0;returnstart;}u_longbus_get_resource_count(device_tdev,inttype,intrid){u_longstart,c
ount;interror;error=BUS_GET_RESOURCE(device_get_parent(dev),dev,type,rid,&start,&count);if(error)return0;returncount;}voidbus_delete_resource(device_tdev,inttype,intrid){BUS_DELETE_RESOURCE(device_get_parent(dev),dev,type,rid);}staticintroot_print_child(device_tdev,device_tchild){return(0);}staticintroot_setup_intr(device_tdev,device_tchild,driver_intr_t*intr,void*arg,void**cookiep){/**Ifaninterruptmappinggetstoheresomethingbadhashappened.*/panic
("root_setup_intr");}staticdevice_method_troot_methods[]={/*Deviceinterface*/DEVMETHOD(device_shutdown,bus_generic_shutdown),DEVMETHOD(device_suspend,bus_generic_suspend),DEVMETHOD(device_resume,bus_generic_resume),/*Businterface*/DEVMETHOD(bus_print_child,root_print_child),DEVMETHOD(bus_read_ivar,bus_generic_read_ivar),DEVMETHOD(bus_write_ivar,bus_generic_write_ivar),DEVMETHOD(bus_setup_intr,root_setup_intr),{0,0}};staticdriver_troot_driver={"ro
ot",root_methods,1,/*nosoftc*/};device_troot_bus;devclass_troot_devclass;staticintroot_bus_module_handler(module_tmod,intwhat,void*arg){switch(what){caseMOD_LOAD:compile_methods(&root_driver);root_bus=make_device(NULL,"root",0);root_bus->desc="Systemrootbus";root_bus->ops=root_driver.ops;root_bus->driver=&root_driver;root_bus->state=DS_ATTACHED;root_devclass=devclass_find_internal("root",FALSE);return0;caseMOD_SHUTDOWN:device_shutdown(root_bus);r
eturn0;}return0;}staticmoduledata_troot_bus_mod={"rootbus",root_bus_module_handler,0};DECLARE_MODULE(rootbus,root_bus_mod,SI_SUB_DRIVERS,SI_ORDER_FIRST);voidroot_bus_configure(void){device_tdev;PDEBUG(("."));for(dev=TAILQ_FIRST(&root_bus->children);dev;dev=TAILQ_NEXT(dev,link)){device_probe_and_attach(dev);}}intdriver_module_handler(module_tmod,intwhat,void*arg){interror,i;structdriver_module_data*dmd;devclass_tbus_devclass;dmd=(structdriver_modu
le_data*)arg;bus_devclass=devclass_find_internal(dmd->dmd_busname,TRUE);error=0;switch(what){caseMOD_LOAD:if(dmd->dmd_chainevh)error=dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);for(i=0;!error&&i<dmd->dmd_ndrivers;i++){PDEBUG(("Loadingmodule:driver%sonbus%s",DRIVERNAME(dmd->dmd_drivers[i]),dmd->dmd_busname));error=devclass_add_driver(bus_devclass,dmd->dmd_drivers[i]);}if(error)break;/**Thedriversloadedinthiswayareassumedtoall*implementthesamedev
class.*/*dmd->dmd_devclass=devclass_find_internal(dmd->dmd_drivers[0]->name,TRUE);break;caseMOD_UNLOAD:for(i=0;!error&&i<dmd->dmd_ndrivers;i++){PDEBUG(("Unloadingmodule:driver%sfrombus%s",DRIVERNAME(dmd->dmd_drivers[i]),dmd->dmd_busname));error=devclass_delete_driver(bus_devclass,dmd->dmd_drivers[i]);}if(!error&&dmd->dmd_chainevh)error=dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);break;}return(error);}#ifdefBUS_DEBUG/*the_shortversionsavoiditera
tionbynotcallinganythingthatprints*morethanoneliners.Iloveoneliners.*/staticvoidprint_method_list(device_method_t*m,intindent){inti;if(!m)return;for(i=0;m->desc;i++,m++)indentprintf(("method%d:%s,offset=%d\n",i,m->desc->name,m->desc->offset));}staticvoidprint_device_ops(device_ops_tops,intindent){inti;intcount=0;if(!ops)return;/*wepresentalistofthemethodsthatarepointingtothe*error_method,butignorethe0'thelements;itisalways*error_method.*/for(i=1;
i<ops->maxoffset;i++){if(ops->methods[i]==error_method){if(count==0)indentprintf(("error_method:"));printf("%d",i);count++;}}if(count)printf("\n");indentprintf(("(%dmethod%s,%dvalid,%derror_method%s)\n",ops->maxoffset-1,(ops->maxoffset-1==1?"":"s"),ops->maxoffset-1-count,count,(count==1?"":"'s")));}staticvoidprint_device_short(device_tdev,intindent){if(!dev)return;indentprintf(("device%d:<%s>%sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n"
,dev->unit,dev->desc,(dev->parent?"":"no"),(TAILQ_EMPTY(&dev->children)?"no":""),(dev->flags&DF_ENABLED?"enabled,":"disabled,"),(dev->flags&DF_FIXEDCLASS?"fixed,":""),(dev->flags&DF_WILDCARD?"wildcard,":""),(dev->flags&DF_DESCMALLOCED?"descmalloced,":""),(dev->ivars?"":"no"),(dev->softc?"":"no"),dev->busy));}staticvoidprint_device(device_tdev,intindent){if(!dev)return;print_device_short(dev,indent);indentprintf(("Parent:\n"));print_device_short(d
ev->parent,indent+1);indentprintf(("Methods:\n"));print_device_ops(dev->ops,indent+1);indentprintf(("Driver:\n"));print_driver_short(dev->driver,indent+1);indentprintf(("Devclass:\n"));print_devclass_short(dev->devclass,indent+1);}voidprint_device_tree_short(device_tdev,intindent)/*printthedeviceandallitschildren(indented)*/{device_tchild;if(!dev)return;print_device_short(dev,indent);for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(ch
ild,link))print_device_tree_short(child,indent+1);}voidprint_device_tree(device_tdev,intindent)/*printthedeviceandallitschildren(indented)*/{device_tchild;if(!dev)return;print_device(dev,indent);for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link))print_device_tree(child,indent+1);}staticvoidprint_driver_short(driver_t*driver,intindent){if(!driver)return;indentprintf(("driver%s:softcsize=%d\n",driver->name,driver->softc));}sta
ticvoidprint_driver(driver_t*driver,intindent){if(!driver)return;print_driver_short(driver,indent);indentprintf(("Methods:\n"));print_method_list(driver->methods,indent+1);indentprintf(("Operations:\n"));print_device_ops(driver->ops,indent+1);}staticvoidprint_driver_list(driver_list_tdrivers,intindent){driverlink_tdriver;for(driver=TAILQ_FIRST(&drivers);driver;driver=TAILQ_NEXT(driver,link))print_driver(driver->driver,indent);}staticvoidprint_dev
class_short(devclass_tdc,intindent){if(!dc)return;indentprintf(("devclass%s:maxunits=%d\n",dc->name,dc->maxunit));}staticvoidprint_devclass(devclass_tdc,intindent){inti;if(!dc)return;print_devclass_short(dc,indent);indentprintf(("Drivers:\n"));print_driver_list(dc->drivers,indent+1);indentprintf(("Devices:\n"));for(i=0;i<dc->maxunit;i++)if(dc->devices[i])print_device(dc->devices[i],indent+1);}voidprint_devclass_list_short(void){devclass_tdc;print
f("Shortlistingofdevclasses,drivers&devices:\n");for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))print_devclass_short(dc,0);}voidprint_devclass_list(void){devclass_tdc;printf("Fulllistingofdevclasses,drivers&devices:\n");for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))print_devclass(dc,0);}#endif/**Copyright(c)1993,DavidGreenman*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermit
tedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITE
DTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWA
Y*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/kern_exec.c,v1.107.2.142002/04/2113:06:23nectarExp$*/#include<sys/param.h>#include<sys/systm.h>#include<sys/sysproto.h>#include<sys/kernel.h>#include<sys/mount.h>#include<sys/filedesc.h>#include<sys/fcntl.h>#include<sys/acct.h>#include<sys/exec.h>#include<sys/imgact.h>#include<sys/imgact_elf.h>#include<sys/wait.h>#include<sys/malloc.h>#include<sys/proc.
h>#include<sys/signalvar.h>#include<sys/pioctl.h>#include<sys/namei.h>#include<sys/sysent.h>#include<sys/shm.h>#include<sys/sysctl.h>#include<sys/vnode.h>#include<sys/aio.h>#include<vm/vm.h>#include<vm/vm_param.h>#include<sys/lock.h>#include<vm/pmap.h>#include<vm/vm_page.h>#include<vm/vm_map.h>#include<vm/vm_kern.h>#include<vm/vm_extern.h>#include<vm/vm_object.h>#include<vm/vm_pager.h>#include<sys/user.h>#include<machine/reg.h>MALLOC_DEFINE(M_PAR
GS,"proc-args","Processarguments");staticregister_t*exec_copyout_strings__P((structimage_params*));/*XXXThisshouldbevm_size_t.*/staticu_longps_strings=PS_STRINGS;SYSCTL_ULONG(_kern,KERN_PS_STRINGS,ps_strings,CTLFLAG_RD,&ps_strings,0,"");/*XXXThisshouldbevm_size_t.*/staticu_longusrstack=USRSTACK;SYSCTL_ULONG(_kern,KERN_USRSTACK,usrstack,CTLFLAG_RD,&usrstack,0,"");u_longps_arg_cache_limit=PAGE_SIZE/16;SYSCTL_LONG(_kern,OID_AUTO,ps_arg_cache_limit,C
TLFLAG_RW,&ps_arg_cache_limit,0,"");intps_argsopen=1;SYSCTL_INT(_kern,OID_AUTO,ps_argsopen,CTLFLAG_RW,&ps_argsopen,0,"");/**Eachoftheitemsisapointertoa`conststructexecsw',hencethe*doublepointerhere.*/staticconststructexecsw**execsw;#ifndef_SYS_SYSPROTO_H_structexecve_args{char*fname;char**argv;char**envv;};#endif/**execve()systemcall.*/intexecve(p,uap)structproc*p;registerstructexecve_args*uap;{structnameidatand,*ndp;register_t*stack_base;interro
r,len,i;structimage_paramsimage_params,*imgp;structvattrattr;int(*img_first)__P((structimage_params*));imgp=&image_params;/**LocktheprocessandsettheP_INEXECflagtoindicatethat*itshouldbeleftaloneuntilwe'redonehere.Thisis*necessarytoavoidraceconditions-e.g.inptrace()-*thatmightallowalocalusertoillicitlyobtainelevated*privileges.*/p->p_flag|=P_INEXEC;/**Initializepartofthecommondata*/imgp->proc=p;imgp->uap=uap;imgp->attr=&attr;imgp->argc=imgp->envc=
0;imgp->argv0=NULL;imgp->entry_addr=0;imgp->vmspace_destroyed=0;imgp->interpreted=0;imgp->interpreter_name[0]='\0';imgp->auxargs=NULL;imgp->vp=NULL;imgp->firstpage=NULL;imgp->ps_strings=0;/**Allocatetemporarydemandzeroedspaceforargumentand*environmentstrings*/imgp->stringbase=(char*)kmem_alloc_wait(exec_map,ARG_MAX+PAGE_SIZE);if(imgp->stringbase==NULL){error=ENOMEM;gotoexec_fail;}imgp->stringp=imgp->stringbase;imgp->stringspace=ARG_MAX;imgp->imag
e_header=imgp->stringbase+ARG_MAX;/**Translatethefilename.namei()returnsavnodepointer*inni_vpamoungotherthings.*/ndp=&nd;NDINIT(ndp,LOOKUP,LOCKLEAF|FOLLOW|SAVENAME,UIO_USERSPACE,uap->fname,p);interpret:error=namei(ndp);if(error){kmem_free_wakeup(exec_map,(vm_offset_t)imgp->stringbase,ARG_MAX+PAGE_SIZE);gotoexec_fail;}imgp->vp=ndp->ni_vp;imgp->fname=uap->fname;/**Checkfilepermissions(also'opens'file)*/error=exec_check_permissions(imgp);if(error){V
OP_UNLOCK(imgp->vp,0,p);gotoexec_fail_dealloc;}error=exec_map_first_page(imgp);VOP_UNLOCK(imgp->vp,0,p);if(error)gotoexec_fail_dealloc;/**Ifthecurrentprocesshasaspecialimageactivatorit*wantstotryfirst,callit.Forexample,emulatingshell*scriptsdifferently.*/error=-1;if((img_first=imgp->proc->p_sysent->sv_imgact_try)!=NULL)error=img_first(imgp);/**Loopthroughthelistofimageactivators,callingeachone.*Anactivatorreturns-1ifthereisnomatch,0onsuccess,*and
anerrorotherwise.*/for(i=0;error==-1&&execsw[i];++i){if(execsw[i]->ex_imgact==NULL||execsw[i]->ex_imgact==img_first){continue;}error=(*execsw[i]->ex_imgact)(imgp);}if(error){if(error==-1)error=ENOEXEC;gotoexec_fail_dealloc;}/**Specialinterpreteroperation,cleanupandloopuptotryto*activatetheinterpreter.*/if(imgp->interpreted){exec_unmap_first_page(imgp);/*freenamebufferandoldvnode*/NDFREE(ndp,NDF_ONLY_PNBUF);vrele(ndp->ni_vp);/*setnewnametothatofth
einterpreter*/NDINIT(ndp,LOOKUP,LOCKLEAF|FOLLOW|SAVENAME,UIO_SYSSPACE,imgp->interpreter_name,p);gotointerpret;}/**Copyoutstrings(argsandenv)andinitializestackbase*/stack_base=exec_copyout_strings(imgp);p->p_vmspace->vm_minsaddr=(char*)stack_base;/**Ifcustomstackfixuproutinepresentforthisprocess*letitdothestacksetup.*Elsestuffargumentcountasfirstitemonstack*/if(p->p_sysent->sv_fixup)(*p->p_sysent->sv_fixup)(&stack_base,imgp);elsesuword(--stack_bas
e,imgp->argc);/**Forsecurityandotherreasons,thefiledescriptortablecannot*besharedafteranexec.*/if(p->p_fd->fd_refcnt>1){structfiledesc*tmp;tmp=fdcopy(p);fdfree(p);p->p_fd=tmp;}/**Forsecurityandotherreasons,signalhandlerscannot*besharedafteranexec.Thenewprocesgetsacopyoftheold*handlers.Inexecsigs(),thenewprocesswillhaveitssignals*reset.*/if(p->p_procsig->ps_refcnt>1){structprocsig*newprocsig;MALLOC(newprocsig,structprocsig*,sizeof(structprocsig),M
_SUBPROC,M_WAITOK);bcopy(p->p_procsig,newprocsig,sizeof(*newprocsig));p->p_procsig->ps_refcnt--;p->p_procsig=newprocsig;p->p_procsig->ps_refcnt=1;if(p->p_sigacts==&p->p_addr->u_sigacts)panic("sharedprocsigbutprivatesigacts?");p->p_addr->u_sigacts=*p->p_sigacts;p->p_sigacts=&p->p_addr->u_sigacts;}/*Stopprofiling*/stopprofclock(p);/*closefilesonexec*/fdcloseexec(p);/*resetcaughtsignals*/execsigs(p);/*namethisprocess-nameiexec(p,ndp)*/len=min(ndp->n
i_cnd.cn_namelen,MAXCOMLEN);bcopy(ndp->ni_cnd.cn_nameptr,p->p_comm,len);p->p_comm[len]=0;/**markasexeced,wakeuptheprocessthatvforked(ifany)andtell*itthatitnowhasitsownresourcesback*/p->p_flag|=P_EXEC;if(p->p_pptr&&(p->p_flag&P_PPWAIT)){p->p_flag&=~P_PPWAIT;wakeup((caddr_t)p->p_pptr);}/**Implementimagesetuid/setgid.**Don'thonorsetuid/setgidifthefilesystemprohibitsitorif*theprocessisbeingtraced.*/if((((attr.va_mode&VSUID)&&p->p_ucred->cr_uid!=attr.
va_uid)||((attr.va_mode&VSGID)&&p->p_ucred->cr_gid!=attr.va_gid))&&(imgp->vp->v_mount->mnt_flag&MNT_NOSUID)==0&&(p->p_flag&P_TRACED)==0){/**Turnoffsyscalltracingforset-idprograms,exceptfor*root.Recordanyset-idflagsfirsttomakesurethat*wedonotregainanytracingduringapossibleblock.*/setsugid(p);if(p->p_tracep&&suser(p)){structvnode*vtmp;if((vtmp=p->p_tracep)!=NULL){p->p_tracep=NULL;p->p_traceflag=0;vrele(vtmp);}}/*Makesurefiledescriptors0..2areinuse.
*/error=fdcheckstd(p);if(error!=0)gotoexec_fail_dealloc;/**Setthenewcredentials.*/p->p_ucred=crcopy(p->p_ucred);if(attr.va_mode&VSUID)change_euid(p,attr.va_uid);if(attr.va_mode&VSGID)p->p_ucred->cr_gid=attr.va_gid;setugidsafety(p);}else{if(p->p_ucred->cr_uid==p->p_cred->p_ruid&&p->p_ucred->cr_gid==p->p_cred->p_rgid)p->p_flag&=~P_SUGID;}/**ImplementcorrectPOSIXsaved-idbehavior.*/p->p_cred->p_svuid=p->p_ucred->cr_uid;p->p_cred->p_svgid=p->p_ucred->
cr_gid;/**Storethevpforuseinprocfs*/if(p->p_textvp)/*releaseoldreference*/vrele(p->p_textvp);VREF(ndp->ni_vp);p->p_textvp=ndp->ni_vp;/**Notifyothersthatweexec'd,andcleartheP_INEXECflag*aswe'renowabonafidefreshly-execedprocess.*/KNOTE(&p->p_klist,NOTE_EXEC);p->p_flag&=~P_INEXEC;/**Iftracingtheprocess,traptodebuggersobreakpoints*canbesetbeforetheprogramexecutes.*/STOPEVENT(p,S_EXEC,0);if(p->p_flag&P_TRACED)psignal(p,SIGTRAP);/*clear"forkbutnoexec"f
lag,aswe_are_execing*/p->p_acflag&=~AFORK;/*Setvaluespassedintotheprograminregisters.*/setregs(p,imgp->entry_addr,(u_long)(uintptr_t)stack_base,imgp->ps_strings);/*Freeanypreviousargumentcache*/if(p->p_args&&--p->p_args->ar_ref==0)FREE(p->p_args,M_PARGS);p->p_args=NULL;/*Cacheargumentsiftheyfitinsideourallowance*/i=imgp->endargs-imgp->stringbase;if(ps_arg_cache_limit>=i+sizeof(structpargs)){MALLOC(p->p_args,structpargs*,sizeof(structpargs)+i,M_PA
RGS,M_WAITOK);p->p_args->ar_ref=1;p->p_args->ar_length=i;bcopy(imgp->stringbase,p->p_args->ar_args,i);}exec_fail_dealloc:/**freevariousallocatedresources*/if(imgp->firstpage)exec_unmap_first_page(imgp);if(imgp->stringbase!=NULL)kmem_free_wakeup(exec_map,(vm_offset_t)imgp->stringbase,ARG_MAX+PAGE_SIZE);if(imgp->vp){NDFREE(ndp,NDF_ONLY_PNBUF);vrele(imgp->vp);}if(error==0)return(0);exec_fail:/*we'redonehere,clearP_INEXEC*/p->p_flag&=~P_INEXEC;if(img
p->vmspace_destroyed){/*sorry,nomoreprocessanymore.exitgracefully*/exit1(p,W_EXITCODE(0,SIGABRT));/*NOTREACHED*/return(0);}else{return(error);}}intexec_map_first_page(imgp)structimage_params*imgp;{ints,rv,i;intinitial_pagein;vm_page_tma[VM_INITIAL_PAGEIN];vm_object_tobject;if(imgp->firstpage){exec_unmap_first_page(imgp);}VOP_GETVOBJECT(imgp->vp,&object);s=splvm();ma[0]=vm_page_grab(object,0,VM_ALLOC_NORMAL|VM_ALLOC_RETRY);if((ma[0]->valid&VM_PAGE
_BITS_ALL)!=VM_PAGE_BITS_ALL){initial_pagein=VM_INITIAL_PAGEIN;if(initial_pagein>object->size)initial_pagein=object->size;for(i=1;i<initial_pagein;i++){if((ma[i]=vm_page_lookup(object,i))!=NULL){if((ma[i]->flags&PG_BUSY)||ma[i]->busy)break;if(ma[i]->valid)break;vm_page_busy(ma[i]);}else{ma[i]=vm_page_alloc(object,i,VM_ALLOC_NORMAL);if(ma[i]==NULL)break;}}initial_pagein=i;rv=vm_pager_get_pages(object,ma,initial_pagein,0);ma[0]=vm_page_lookup(objec
t,0);if((rv!=VM_PAGER_OK)||(ma[0]==NULL)||(ma[0]->valid==0)){if(ma[0]){vm_page_protect(ma[0],VM_PROT_NONE);vm_page_free(ma[0]);}splx(s);returnEIO;}}vm_page_wire(ma[0]);vm_page_wakeup(ma[0]);splx(s);pmap_kenter((vm_offset_t)imgp->image_header,VM_PAGE_TO_PHYS(ma[0]));imgp->firstpage=ma[0];return0;}voidexec_unmap_first_page(imgp)structimage_params*imgp;{if(imgp->firstpage){pmap_kremove((vm_offset_t)imgp->image_header);vm_page_unwire(imgp->firstpage,
1);imgp->firstpage=NULL;}}/**Destroyoldaddressspace,andallocateanewstack*ThenewstackisonlySGROWSIZlargebecauseitisgrown*automaticallyintrap.c.*/intexec_new_vmspace(imgp)structimage_params*imgp;{interror;structvmspace*vmspace=imgp->proc->p_vmspace;vm_offset_tstack_addr=USRSTACK-maxssiz;vm_map_tmap=&vmspace->vm_map;imgp->vmspace_destroyed=1;/**PreventapendingAIOfrommodifyingthenewaddressspace.*/aio_proc_rundown(imgp->proc);/**BlowawayentireprocessV
M,ifaddressspacenotshared,*otherwise,createanewVMspacesothatotherthreadsare*notdisrupted*/if(vmspace->vm_refcnt==1){if(vmspace->vm_shm)shmexit(imgp->proc);pmap_remove_pages(vmspace_pmap(vmspace),0,VM_MAXUSER_ADDRESS);vm_map_remove(map,0,VM_MAXUSER_ADDRESS);}else{vmspace_exec(imgp->proc);vmspace=imgp->proc->p_vmspace;map=&vmspace->vm_map;}/*Allocateanewstack*/error=vm_map_stack(&vmspace->vm_map,stack_addr,(vm_size_t)maxssiz,VM_PROT_ALL,VM_PROT_ALL
,0);if(error)return(error);/*vm_ssizeandvm_maxsaddraresomewhatantiquatedconceptsinthe*VM_STACKcase,buttheyarestillusedtomonitorthesizeofthe*processstacksowecancheckthestackrlimit.*/vmspace->vm_ssize=sgrowsiz>>PAGE_SHIFT;vmspace->vm_maxsaddr=(char*)USRSTACK-maxssiz;return(0);}/**Copyoutargumentandenvironmentstringsfromtheoldprocess*addressspaceintothetemporarystringbuffer.*/intexec_extract_strings(imgp)structimage_params*imgp;{char**argv,**envv;ch
ar*argp,*envp;interror;size_tlength;/**extractargumentsfirst*/argv=imgp->uap->argv;if(argv){argp=(caddr_t)(intptr_t)fuword(argv);if(argp==(caddr_t)-1)return(EFAULT);if(argp)argv++;if(imgp->argv0)argp=imgp->argv0;if(argp){do{if(argp==(caddr_t)-1)return(EFAULT);if((error=copyinstr(argp,imgp->stringp,imgp->stringspace,&length))){if(error==ENAMETOOLONG)return(E2BIG);return(error);}imgp->stringspace-=length;imgp->stringp+=length;imgp->argc++;}while((a
rgp=(caddr_t)(intptr_t)fuword(argv++)));}}imgp->endargs=imgp->stringp;/**extractenvironmentstrings*/envv=imgp->uap->envv;if(envv){while((envp=(caddr_t)(intptr_t)fuword(envv++))){if(envp==(caddr_t)-1)return(EFAULT);if((error=copyinstr(envp,imgp->stringp,imgp->stringspace,&length))){if(error==ENAMETOOLONG)return(E2BIG);return(error);}imgp->stringspace-=length;imgp->stringp+=length;imgp->envc++;}}return(0);}/**Copystringsouttothenewprocessaddressspa
ce,constructing*newargandenvvectortables.Returnapointertothebase*sothatitcanbeusedastheinitialstackpointer.*/register_t*exec_copyout_strings(imgp)structimage_params*imgp;{intargc,envc;char**vectp;char*stringp,*destp;register_t*stack_base;structps_strings*arginfo;intszsigcode;/**Calculatestringbaseandvectortablepointers.*Alsodealwithsignaltrampolinecodeforthisexectype.*/arginfo=(structps_strings*)PS_STRINGS;szsigcode=*(imgp->proc->p_sysent->sv_szs
igcode);destp=(caddr_t)arginfo-szsigcode-SPARE_USRSPACE-roundup((ARG_MAX-imgp->stringspace),sizeof(char*));/**installsigcode*/if(szsigcode)copyout(imgp->proc->p_sysent->sv_sigcode,((caddr_t)arginfo-szsigcode),szsigcode);/**Ifwehaveavalidauxargsptr,preparesomeroom*onthestack.*/if(imgp->auxargs)/**The'+2'isforthenullpointersattheendofeachofthe*argandenvvectorsets,and'AT_COUNT*2'isroomforthe*ELFAuxargsdata.*/vectp=(char**)(destp-(imgp->argc+imgp->en
vc+2+AT_COUNT*2)*sizeof(char*));else/**The'+2'isforthenullpointersattheendofeachofthe*argandenvvectorsets*/vectp=(char**)(destp-(imgp->argc+imgp->envc+2)*sizeof(char*));/**vectpalsobecomesourinitialstackbase*/stack_base=(register_t*)vectp;stringp=imgp->stringbase;argc=imgp->argc;envc=imgp->envc;/**Copyoutstrings-argumentsandenvironment.*/copyout(stringp,destp,ARG_MAX-imgp->stringspace);/**Fillin"ps_strings"structforps,w,etc.*/suword(&arginfo->ps_
argvstr,(long)(intptr_t)vectp);suword(&arginfo->ps_nargvstr,argc);/**Fillinargumentportionofvectortable.*/for(;argc>0;--argc){suword(vectp++,(long)(intptr_t)destp);while(*stringp++!=0)destp++;destp++;}/*anullvectortablepointerseperatestheargp'sfromtheenvp's*/suword(vectp++,0);suword(&arginfo->ps_envstr,(long)(intptr_t)vectp);suword(&arginfo->ps_nenvstr,envc);/**Fillinenvironmentportionofvectortable.*/for(;envc>0;--envc){suword(vectp++,(long)(intp
tr_t)destp);while(*stringp++!=0)destp++;destp++;}/*endofvectortableisanullpointer*/suword(vectp,0);return(stack_base);}/**Checkpermissionsoffiletoexecute.*Return0forsuccessorerrorcodeonfailure.*/intexec_check_permissions(imgp)structimage_params*imgp;{structproc*p=imgp->proc;structvnode*vp=imgp->vp;structvattr*attr=imgp->attr;interror;/*Getfileattributes*/error=VOP_GETATTR(vp,attr,p->p_ucred,p);if(error)return(error);/**1)Checkiffileexecutionisdis
abledforthefilesystemthatthis*fileresideson.*2)Insurethatatleastoneexecutebitison-otherwiseroot*willalwayssucceed,andwedon'twanttohappenunlessthe*filereallyisexecutable.*3)Insurethatthefileisaregularfile.*/if((vp->v_mount->mnt_flag&MNT_NOEXEC)||((attr->va_mode&0111)==0)||(attr->va_type!=VREG)){return(EACCES);}/**Zerolengthfilescan'tbeexec'd*/if(attr->va_size==0)return(ENOEXEC);/**Checkforexecutepermissiontofilebasedoncurrentcredentials.*/error=VO
P_ACCESS(vp,VEXEC,p->p_ucred,p);if(error)return(error);/**Checknumberofopen-for-writesonthefileanddenyexecution*ifthereareany.*/if(vp->v_writecount)return(ETXTBSY);/**Callfilesystemspecificopenroutine(whichdoesnothinginthe*generalcase).*/error=VOP_OPEN(vp,FREAD,p->p_ucred,p);if(error)return(error);return(0);}/**Exechandlerregistration*/intexec_register(execsw_arg)conststructexecsw*execsw_arg;{conststructexecsw**es,**xs,**newexecsw;intcount=2;/*Ne
wslotandtrailingNULL*/if(execsw)for(es=execsw;*es;es++)count++;newexecsw=malloc(count*sizeof(*es),M_TEMP,M_WAITOK);if(newexecsw==NULL)returnENOMEM;xs=newexecsw;if(execsw)for(es=execsw;*es;es++)*xs++=*es;*xs++=execsw_arg;*xs=NULL;if(execsw)free(execsw,M_TEMP);execsw=newexecsw;return0;}intexec_unregister(execsw_arg)conststructexecsw*execsw_arg;{conststructexecsw**es,**xs,**newexecsw;intcount=1;if(execsw==NULL)panic("unregisterwithnohandlersleft?\n"
);for(es=execsw;*es;es++){if(*es==execsw_arg)break;}if(*es==NULL)returnENOENT;for(es=execsw;*es;es++)if(*es!=execsw_arg)count++;newexecsw=malloc(count*sizeof(*es),M_TEMP,M_WAITOK);if(newexecsw==NULL)returnENOMEM;xs=newexecsw;for(es=execsw;*es;es++)if(*es!=execsw_arg)*xs++=*es;*xs=NULL;if(execsw)free(execsw,M_TEMP);execsw=newexecsw;return0;}/**Copyright(c)1993,DavidGreenman*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwitho
ut*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTI
ES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEO
ROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/imgact_aout.c,v1.59.2.52001/11/0301:41:08psExp$*/#include<sys/param.h>#include<sys/resourcevar.h>#include<sys/exec.h>#include<sys/fcntl.h>#include<sys/imgact.h>#include<sys/imgact_aout.h>#include<sys/kernel.h>#include<sys/malloc.h>#include<sys/namei.h>#include<sys/pioctl.h>#include<sys/proc.h>#include<sys/signalvar.h>#include<sy
s/stat.h>#include<sys/sysent.h>#include<sys/syscall.h>#include<sys/vnode.h>#include<sys/systm.h>#include<machine/md_var.h>#include<vm/vm.h>#include<vm/vm_param.h>#include<sys/lock.h>#include<vm/pmap.h>#include<vm/vm_map.h>#include<vm/vm_object.h>#include<sys/user.h>staticintexec_aout_imgact__P((structimage_params*imgp));structsysentvecaout_sysvec={SYS_MAXSYSCALL,sysent,0,0,0,0,0,0,0,sendsig,sigcode,&szsigcode,0,"FreeBSDa.out",aout_coredump,NULL,M
INSIGSTKSZ};staticintexec_aout_imgact(imgp)structimage_params*imgp;{conststructexec*a_out=(conststructexec*)imgp->image_header;structvmspace*vmspace;structvnode*vp;vm_map_tmap;vm_object_tobject;vm_offset_ttext_end,data_end;unsignedlongvirtual_offset;unsignedlongfile_offset;unsignedlongbss_size;interror;/**Linuxand*BSDbinarieslookverymuchalike,*onlythemachineidisdifferent:*0x64forLinux,0x86for*BSD,0x00forBSDI.*NetBSDisinnetworkbyteorder..ugh.*/if(
((a_out->a_magic>>16)&0xff)!=0x86&&((a_out->a_magic>>16)&0xff)!=0&&((((int)ntohl(a_out->a_magic))>>16)&0xff)!=0x86)return-1;/**Setfile/virtualoffsetbasedona.outvariant.*Wedotwocases:hostbyteorderandnetworkbyteorder*(forNetBSDcompatibility)*/switch((int)(a_out->a_magic&0xffff)){caseZMAGIC:virtual_offset=0;if(a_out->a_text){file_offset=PAGE_SIZE;}else{/*Bill's"screwballmode"*/file_offset=0;}break;caseQMAGIC:virtual_offset=PAGE_SIZE;file_offset=0;/*
PassPS_STRINGSforBSD/OSbinariesonly.*/if(N_GETMID(*a_out)==MID_ZERO)imgp->ps_strings=PS_STRINGS;break;default:/*NetBSDcompatibility*/switch((int)(ntohl(a_out->a_magic)&0xffff)){caseZMAGIC:caseQMAGIC:virtual_offset=PAGE_SIZE;file_offset=0;break;default:return(-1);}}bss_size=roundup(a_out->a_bss,PAGE_SIZE);/**Checkvariousfieldsinheaderforvalidity/bounds.*/if(/*entrypointmustlaywithtextregion*/a_out->a_entry<virtual_offset||a_out->a_entry>=virtual_o
ffset+a_out->a_text||/*textanddatasizemusteachbepagerounded*/a_out->a_text&PAGE_MASK||a_out->a_data&PAGE_MASK)return(-1);/*text+datacan'texceedfilesize*/if(a_out->a_data+a_out->a_text>imgp->attr->va_size)return(EFAULT);/**text/data/bssmustnotexceedlimits*/if(/*textcan'texceedmaximumtextsize*/a_out->a_text>maxtsiz||/*data+bsscan'texceedrlimit*/a_out->a_data+bss_size>imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur)return(ENOMEM);/*copyinargumentsand/ore
nvironmentfromoldprocess*/error=exec_extract_strings(imgp);if(error)return(error);/**DestroyoldprocessVMandcreateanewone(withanewstack)*/exec_new_vmspace(imgp);/**Thevmspacecanbechangedbyexec_new_vmspace*/vmspace=imgp->proc->p_vmspace;vp=imgp->vp;map=&vmspace->vm_map;vm_map_lock(map);VOP_GETVOBJECT(vp,&object);vm_object_reference(object);text_end=virtual_offset+a_out->a_text;error=vm_map_insert(map,object,file_offset,virtual_offset,text_end,VM_PR
OT_READ|VM_PROT_EXECUTE,VM_PROT_ALL,MAP_COPY_ON_WRITE|MAP_PREFAULT);if(error){vm_map_unlock(map);return(error);}data_end=text_end+a_out->a_data;if(a_out->a_data){vm_object_reference(object);error=vm_map_insert(map,object,file_offset+a_out->a_text,text_end,data_end,VM_PROT_ALL,VM_PROT_ALL,MAP_COPY_ON_WRITE|MAP_PREFAULT);if(error){vm_map_unlock(map);return(error);}}if(bss_size){error=vm_map_insert(map,NULL,0,data_end,data_end+bss_size,VM_PROT_ALL,V
M_PROT_ALL,0);if(error){vm_map_unlock(map);return(error);}}vm_map_unlock(map);/*FillinprocessVMinformation*/vmspace->vm_tsize=a_out->a_text>>PAGE_SHIFT;vmspace->vm_dsize=(a_out->a_data+bss_size)>>PAGE_SHIFT;vmspace->vm_taddr=(caddr_t)(uintptr_t)virtual_offset;vmspace->vm_daddr=(caddr_t)(uintptr_t)(virtual_offset+a_out->a_text);/*Fillinimage_params*/imgp->interpreted=0;imgp->entry_addr=a_out->a_entry;imgp->proc->p_sysent=&aout_sysvec;/*Indicatetha
tthisfileshouldnotbemodified*/imgp->vp->v_flag|=VTEXT;return(0);}/**Dumpcore,intoafilenamedasdescribedinthecommentsfor*expand_name(),unlesstheprocesswassetuid/setgid.*/intaout_coredump(p,vp,limit)registerstructproc*p;registerstructvnode*vp;off_tlimit;{registerstructucred*cred=p->p_ucred;registerstructvmspace*vm=p->p_vmspace;interror;if(ctob(UPAGES+vm->vm_dsize+vm->vm_ssize)>=limit)return(EFAULT);bcopy(p,&p->p_addr->u_kproc.kp_proc,sizeof(structpr
oc));fill_eproc(p,&p->p_addr->u_kproc.kp_eproc);error=cpu_coredump(p,vp,cred);if(error==0)error=vn_rdwr_inchunks(UIO_WRITE,vp,vm->vm_daddr,(int)ctob(vm->vm_dsize),(off_t)ctob(UPAGES),UIO_USERSPACE,IO_UNIT|IO_DIRECT,cred,(int*)NULL,p);if(error==0)error=vn_rdwr_inchunks(UIO_WRITE,vp,(caddr_t)trunc_page(USRSTACK-ctob(vm->vm_ssize)),round_page(ctob(vm->vm_ssize)),(off_t)ctob(UPAGES)+ctob(vm->vm_dsize),UIO_USERSPACE,IO_UNIT|IO_DIRECT,cred,(int*)NULL,p
);return(error);}/**Tellkern_execve.caboutit,withalittlehelpfromthelinker.*/staticstructexecswaout_execsw={exec_aout_imgact,"a.out"};EXEC_SET(aout,aout_execsw);/*-*Copyright(c)1995-1996SrenSchmidt*Copyright(c)1996PeterWemm*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditi
onsandthefollowingdisclaimer*inthispositionandunchanged.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.*3.Thenameoftheauthormaynotbeusedtoendorseorpromoteproducts*derivedfromthissoftwarewithoughspecificpriorwrittenpermission**THISSOFTWAREISPROVIDEDBYTHEAUTHOR``ASIS''ANDANYEXPRESSOR*IMPLIEDWARRANTIES,INCLUDING,BUTNOT
LIMITEDTO,THEIMPLIEDWARRANTIES*OFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSEAREDISCLAIMED.*INNOEVENTSHALLTHEAUTHORBELIABLEFORANYDIRECT,INDIRECT,*INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUT*NOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,*DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANY*THEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT*(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTH
EUSEOF*THISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.**$FreeBSD:src/sys/kern/imgact_elf.c,v1.73.2.92001/12/1618:26:16mpExp$*/#include<sys/param.h>#include<sys/exec.h>#include<sys/fcntl.h>#include<sys/imgact.h>#include<sys/imgact_elf.h>#include<sys/kernel.h>#include<sys/malloc.h>#include<sys/mman.h>#include<sys/namei.h>#include<sys/pioctl.h>#include<sys/proc.h>#include<sys/procfs.h>#include<sys/resourcevar.h>#include<sys/signalvar.h>#incl
ude<sys/stat.h>#include<sys/syscall.h>#include<sys/sysctl.h>#include<sys/sysent.h>#include<sys/systm.h>#include<sys/vnode.h>#include<vm/vm.h>#include<vm/vm_kern.h>#include<vm/vm_param.h>#include<vm/pmap.h>#include<sys/lock.h>#include<vm/vm_map.h>#include<vm/vm_object.h>#include<vm/vm_extern.h>#include<machine/elf.h>#include<machine/md_var.h>#defineOLD_EI_BRAND8__ElfType(Brandinfo);__ElfType(Auxargs);staticintelf_check_header__P((constElf_Ehdr*hdr
));staticintelf_freebsd_fixup__P((register_t**stack_base,structimage_params*imgp));staticintelf_load_file__P((structproc*p,constchar*file,u_long*addr,u_long*entry));staticintelf_load_section__P((structproc*p,structvmspace*vmspace,structvnode*vp,vm_offset_toffset,caddr_tvmaddr,size_tmemsz,size_tfilsz,vm_prot_tprot));staticintexec_elf_imgact__P((structimage_params*imgp));staticintelf_trace=0;SYSCTL_INT(_debug,OID_AUTO,elf_trace,CTLFLAG_RW,&elf_trac
e,0,"");staticstructsysentvecelf_freebsd_sysvec={SYS_MAXSYSCALL,sysent,0,0,0,0,0,0,elf_freebsd_fixup,sendsig,sigcode,&szsigcode,0,"FreeBSDELF",elf_coredump,NULL,MINSIGSTKSZ};staticElf_Brandinfofreebsd_brand_info={ELFOSABI_FREEBSD,"FreeBSD","","/usr/libexec/ld-elf.so.1",&elf_freebsd_sysvec};staticElf_Brandinfo*elf_brand_list[MAX_BRANDS]={&freebsd_brand_info,NULL,NULL,NULL,NULL,NULL,NULL,NULL};intelf_insert_brand_entry(Elf_Brandinfo*entry){inti;for
(i=1;i<MAX_BRANDS;i++){if(elf_brand_list[i]==NULL){elf_brand_list[i]=entry;break;}}if(i==MAX_BRANDS)return-1;return0;}intelf_remove_brand_entry(Elf_Brandinfo*entry){inti;for(i=1;i<MAX_BRANDS;i++){if(elf_brand_list[i]==entry){elf_brand_list[i]=NULL;break;}}if(i==MAX_BRANDS)return-1;return0;}intelf_brand_inuse(Elf_Brandinfo*entry){structproc*p;intrval=FALSE;LIST_FOREACH(p,&allproc,p_list){if(p->p_sysent==entry->sysvec){rval=TRUE;break;}}return(rval
);}staticintelf_check_header(constElf_Ehdr*hdr){if(!IS_ELF(*hdr)||hdr->e_ident[EI_CLASS]!=ELF_TARG_CLASS||hdr->e_ident[EI_DATA]!=ELF_TARG_DATA||hdr->e_ident[EI_VERSION]!=EV_CURRENT)returnENOEXEC;if(!ELF_MACHINE_OK(hdr->e_machine))returnENOEXEC;if(hdr->e_version!=ELF_TARG_VER)returnENOEXEC;return0;}staticintelf_load_section(structproc*p,structvmspace*vmspace,structvnode*vp,vm_offset_toffset,caddr_tvmaddr,size_tmemsz,size_tfilsz,vm_prot_tprot){size
_tmap_len;vm_offset_tmap_addr;interror,rv;size_tcopy_len;vm_object_tobject;vm_offset_tfile_addr;vm_offset_tdata_buf=0;VOP_GETVOBJECT(vp,&object);error=0;/**It'snecessarytofailifthefilsz+offsettakenfromthe*headerisgreaterthantheactualfilepagerobject'ssize.*Ifweweretoallowthis,thenthevm_map_find()belowwould*walkrightofftheendofthefileobjectandintotheether.**WhileI'mhere,mightaswellcheckforsomethingelsethat*isinvalid:filszcannotbegreaterthanmemsz.*/
if((off_t)filsz+offset>object->un_pager.vnp.vnp_size||filsz>memsz){uprintf("elf_load_section:truncatedELFfile\n");return(ENOEXEC);}map_addr=trunc_page((vm_offset_t)vmaddr);file_addr=trunc_page(offset);/**Wehavetwochoices.Wecaneitherclearthedatainthelastpage*ofanoversizedmapping,orwecanstarttheanonmappingapage*earlyandcopytheinitializeddataintothatfirstpage.We*choosethesecond..*/if(memsz>filsz)map_len=trunc_page(offset+filsz)-file_addr;elsemap_len
=round_page(offset+filsz)-file_addr;if(map_len!=0){vm_object_reference(object);vm_map_lock(&vmspace->vm_map);rv=vm_map_insert(&vmspace->vm_map,object,file_addr,/*fileoffset*/map_addr,/*virtualstart*/map_addr+map_len,/*virtualend*/prot,VM_PROT_ALL,MAP_COPY_ON_WRITE|MAP_PREFAULT);vm_map_unlock(&vmspace->vm_map);if(rv!=KERN_SUCCESS){vm_object_deallocate(object);returnEINVAL;}/*wecanstopnowifwe'vecovereditall*/if(memsz==filsz){return0;}}/**Wehavetoge
ttheremainingbitofthefileintothefirstpart*oftheoversizedmapsegment.Thisisnormallybecausethe.data*segmentinthefileisextendedtoprovidebss.It'saneatidea*totryandsaveapage,butit'sapaininthebehindtoimplement.*/copy_len=(offset+filsz)-trunc_page(offset+filsz);map_addr=trunc_page((vm_offset_t)vmaddr+filsz);map_len=round_page((vm_offset_t)vmaddr+memsz)-map_addr;/*Thishaddamnwellbetterbetrue!*/if(map_len!=0){vm_map_lock(&vmspace->vm_map);rv=vm_map_insert(
&vmspace->vm_map,NULL,0,map_addr,map_addr+map_len,VM_PROT_ALL,VM_PROT_ALL,0);vm_map_unlock(&vmspace->vm_map);if(rv!=KERN_SUCCESS){returnEINVAL;}}if(copy_len!=0){vm_object_reference(object);rv=vm_map_find(exec_map,object,trunc_page(offset+filsz),&data_buf,PAGE_SIZE,TRUE,VM_PROT_READ,VM_PROT_ALL,MAP_COPY_ON_WRITE|MAP_PREFAULT_PARTIAL);if(rv!=KERN_SUCCESS){vm_object_deallocate(object);returnEINVAL;}/*sendthepagefragmenttouserspace*/error=copyout((ca
ddr_t)data_buf,(caddr_t)map_addr,copy_len);vm_map_remove(exec_map,data_buf,data_buf+PAGE_SIZE);if(error){return(error);}}/**setittothespecifiedprotection*/vm_map_protect(&vmspace->vm_map,map_addr,map_addr+map_len,prot,FALSE);returnerror;}/**Loadthefile"file"intomemory.Itmaybeeitherasharedobject*oranexecutable.**The"addr"referenceparameterisin/out.Onentry,itspecifies*theaddresswhereasharedobjectshouldbeloaded.Ifthefileis*anexecutable,thisvalueisig
nored.Onexit,"addr"specifies*wherethefilewasactuallyloaded.**The"entry"referenceparameterisoutonly.Onexit,itspecifies*theentrypointfortheloadedfile.*/staticintelf_load_file(structproc*p,constchar*file,u_long*addr,u_long*entry){struct{structnameidatand;structvattrattr;structimage_paramsimage_params;}*tempdata;constElf_Ehdr*hdr=NULL;constElf_Phdr*phdr=NULL;structnameidata*nd;structvmspace*vmspace=p->p_vmspace;structvattr*attr;structimage_params*img
p;vm_prot_tprot;u_longrbase;u_longbase_addr=0;interror,i,numsegs;tempdata=malloc(sizeof(*tempdata),M_TEMP,M_WAITOK);nd=&tempdata->nd;attr=&tempdata->attr;imgp=&tempdata->image_params;/**Initializepartofthecommondata*/imgp->proc=p;imgp->uap=NULL;imgp->attr=attr;imgp->firstpage=NULL;imgp->image_header=(char*)kmem_alloc_wait(exec_map,PAGE_SIZE);if(imgp->image_header==NULL){nd->ni_vp=NULL;error=ENOMEM;gotofail;}NDINIT(nd,LOOKUP,LOCKLEAF|FOLLOW,UIO_SY
SSPACE,file,p);if((error=namei(nd))!=0){nd->ni_vp=NULL;gotofail;}NDFREE(nd,NDF_ONLY_PNBUF);imgp->vp=nd->ni_vp;/**Checkpermissions,modes,uid,etconthefile,and"open"it.*/error=exec_check_permissions(imgp);if(error){VOP_UNLOCK(nd->ni_vp,0,p);gotofail;}error=exec_map_first_page(imgp);/**Alsomakecertainthattheinterpreterstaysthesame,soset*itsVTEXTflag,too.*/if(error==0)nd->ni_vp->v_flag|=VTEXT;VOP_UNLOCK(nd->ni_vp,0,p);if(error)gotofail;hdr=(constElf_E
hdr*)imgp->image_header;if((error=elf_check_header(hdr))!=0)gotofail;if(hdr->e_type==ET_DYN)rbase=*addr;elseif(hdr->e_type==ET_EXEC)rbase=0;else{error=ENOEXEC;gotofail;}/*Onlysupportheadersthatfitwithinfirstpagefornow*/if((hdr->e_phoff>PAGE_SIZE)||(hdr->e_phoff+hdr->e_phentsize*hdr->e_phnum)>PAGE_SIZE){error=ENOEXEC;gotofail;}phdr=(constElf_Phdr*)(imgp->image_header+hdr->e_phoff);for(i=0,numsegs=0;i<hdr->e_phnum;i++){if(phdr[i].p_type==PT_LOAD){/
*Loadablesegment*/prot=0;if(phdr[i].p_flags&PF_X)prot|=VM_PROT_EXECUTE;if(phdr[i].p_flags&PF_W)prot|=VM_PROT_WRITE;if(phdr[i].p_flags&PF_R)prot|=VM_PROT_READ;if((error=elf_load_section(p,vmspace,nd->ni_vp,phdr[i].p_offset,(caddr_t)phdr[i].p_vaddr+rbase,phdr[i].p_memsz,phdr[i].p_filesz,prot))!=0)gotofail;/**Establishthebaseaddressifthisisthe*firstsegment.*/if(numsegs==0)base_addr=trunc_page(phdr[i].p_vaddr+rbase);numsegs++;}}*addr=base_addr;*entry
=(unsignedlong)hdr->e_entry+rbase;fail:if(imgp->firstpage)exec_unmap_first_page(imgp);if(imgp->image_header)kmem_free_wakeup(exec_map,(vm_offset_t)imgp->image_header,PAGE_SIZE);if(nd->ni_vp)vrele(nd->ni_vp);free(tempdata,M_TEMP);returnerror;}/**nonstatic,asitcanbeoverriddenbystart_init()*/intfallback_elf_brand=-1;SYSCTL_INT(_kern,OID_AUTO,fallback_elf_brand,CTLFLAG_RW,&fallback_elf_brand,-1,"ELFbrandoflastresort");staticintexec_elf_imgact(structi
mage_params*imgp){constElf_Ehdr*hdr=(constElf_Ehdr*)imgp->image_header;constElf_Phdr*phdr;Elf_Auxargs*elf_auxargs=NULL;structvmspace*vmspace;vm_prot_tprot;u_longtext_size=0,data_size=0;u_longtext_addr=0,data_addr=0;u_longaddr,entry=0,proghdr=0;interror,i;constchar*interp=NULL;Elf_Brandinfo*brand_info;char*path;/**DowehaveavalidELFheader?*/if(elf_check_header(hdr)!=0||hdr->e_type!=ET_EXEC)return-1;/**Fromhereondown,wereturnanerrno,not-1,aswe've*de
tectedanELFfile.*/if((hdr->e_phoff>PAGE_SIZE)||(hdr->e_phoff+hdr->e_phentsize*hdr->e_phnum)>PAGE_SIZE){/*Onlysupportheadersinfirstpagefornow*/returnENOEXEC;}phdr=(constElf_Phdr*)(imgp->image_header+hdr->e_phoff);/**Fromthispointon,wemayhaveresourcesthatneedtobefreed.*//**Yeah,I'mparanoid.Thereiseveryreasonintheworldtoget*VTEXTnowsincefromhereonout,thereareplaceswecanhave*acontextswitch.Bettersafethansorry;Ireallydon'twant*thefiletochangewhileit's
beingloaded.*/simple_lock(&imgp->vp->v_interlock);imgp->vp->v_flag|=VTEXT;simple_unlock(&imgp->vp->v_interlock);if((error=exec_extract_strings(imgp))!=0)gotofail;exec_new_vmspace(imgp);vmspace=imgp->proc->p_vmspace;for(i=0;i<hdr->e_phnum;i++){switch(phdr[i].p_type){casePT_LOAD:/*Loadablesegment*/prot=0;if(phdr[i].p_flags&PF_X)prot|=VM_PROT_EXECUTE;if(phdr[i].p_flags&PF_W)prot|=VM_PROT_WRITE;if(phdr[i].p_flags&PF_R)prot|=VM_PROT_READ;if((error=elf
_load_section(imgp->proc,vmspace,imgp->vp,phdr[i].p_offset,(caddr_t)phdr[i].p_vaddr,phdr[i].p_memsz,phdr[i].p_filesz,prot))!=0)gotofail;/**Isthis.textor.data??**WeonlyhandleoneeachofthoseyetXXX*/if(hdr->e_entry>=phdr[i].p_vaddr&&hdr->e_entry<(phdr[i].p_vaddr+phdr[i].p_memsz)){text_addr=trunc_page(phdr[i].p_vaddr);text_size=round_page(phdr[i].p_memsz+phdr[i].p_vaddr-text_addr);entry=(u_long)hdr->e_entry;}else{data_addr=trunc_page(phdr[i].p_vaddr);
data_size=round_page(phdr[i].p_memsz+phdr[i].p_vaddr-data_addr);}break;casePT_INTERP:/*Pathtointerpreter*/if(phdr[i].p_filesz>MAXPATHLEN||phdr[i].p_offset+phdr[i].p_filesz>PAGE_SIZE){error=ENOEXEC;gotofail;}interp=imgp->image_header+phdr[i].p_offset;break;casePT_PHDR:/*Programheadertableinfo*/proghdr=phdr[i].p_vaddr;break;default:break;}}vmspace->vm_tsize=text_size>>PAGE_SHIFT;vmspace->vm_taddr=(caddr_t)(uintptr_t)text_addr;vmspace->vm_dsize=data
_size>>PAGE_SHIFT;vmspace->vm_daddr=(caddr_t)(uintptr_t)data_addr;addr=ELF_RTLD_ADDR(vmspace);imgp->entry_addr=entry;brand_info=NULL;/*Wesupportthreetypesofbranding--(1)theELFEI_OSABIfield*thatSCOaddedtotheELFspec,(2)FreeBSD3.x'straditionalstring*brandingw/intheELFheader,and(3)pathofthe`interp_path'*field.Weshouldalsolookforan".note.ABI-tag"ELFsectionnow*inallLinuxELFbinaries,FreeBSD4.1+,andsomeNetBSDones.*//*Iftheexecutablehasabrand,searchforiti
nthebrandlist.*/if(brand_info==NULL){for(i=0;i<MAX_BRANDS;i++){Elf_Brandinfo*bi=elf_brand_list[i];if(bi!=NULL&&(hdr->e_ident[EI_OSABI]==bi->brand||0==strncmp((constchar*)&hdr->e_ident[OLD_EI_BRAND],bi->compat_3_brand,strlen(bi->compat_3_brand)))){brand_info=bi;break;}}}/*Lackingaknownbrand,searchforarecognizedinterpreter.*/if(brand_info==NULL&&interp!=NULL){for(i=0;i<MAX_BRANDS;i++){Elf_Brandinfo*bi=elf_brand_list[i];if(bi!=NULL&&strcmp(interp,bi
->interp_path)==0){brand_info=bi;break;}}}/*Lackingarecognizedinterpreter,trythedefaultbrand*/if(brand_info==NULL){for(i=0;i<MAX_BRANDS;i++){Elf_Brandinfo*bi=elf_brand_list[i];if(bi!=NULL&&fallback_elf_brand==bi->brand){brand_info=bi;break;}}}if(brand_info==NULL){uprintf("ELFbinarytype\"%u\"notknown.\n",hdr->e_ident[EI_OSABI]);error=ENOEXEC;gotofail;}imgp->proc->p_sysent=brand_info->sysvec;if(interp!=NULL){path=malloc(MAXPATHLEN,M_TEMP,M_WAITOK);
snprintf(path,MAXPATHLEN,"%s%s",brand_info->emul_path,interp);if((error=elf_load_file(imgp->proc,path,&addr,&imgp->entry_addr))!=0){if((error=elf_load_file(imgp->proc,interp,&addr,&imgp->entry_addr))!=0){uprintf("ELFinterpreter%snotfound\n",path);free(path,M_TEMP);gotofail;}}free(path,M_TEMP);}/**Constructauxargstable(usedbythefixuproutine)*/elf_auxargs=malloc(sizeof(Elf_Auxargs),M_TEMP,M_WAITOK);elf_auxargs->execfd=-1;elf_auxargs->phdr=proghdr;e
lf_auxargs->phent=hdr->e_phentsize;elf_auxargs->phnum=hdr->e_phnum;elf_auxargs->pagesz=PAGE_SIZE;elf_auxargs->base=addr;elf_auxargs->flags=0;elf_auxargs->entry=entry;elf_auxargs->trace=elf_trace;imgp->auxargs=elf_auxargs;imgp->interpreted=0;fail:returnerror;}staticintelf_freebsd_fixup(register_t**stack_base,structimage_params*imgp){Elf_Auxargs*args=(Elf_Auxargs*)imgp->auxargs;register_t*pos;pos=*stack_base+(imgp->argc+imgp->envc+2);if(args->trace
){AUXARGS_ENTRY(pos,AT_DEBUG,1);}if(args->execfd!=-1){AUXARGS_ENTRY(pos,AT_EXECFD,args->execfd);}AUXARGS_ENTRY(pos,AT_PHDR,args->phdr);AUXARGS_ENTRY(pos,AT_PHENT,args->phent);AUXARGS_ENTRY(pos,AT_PHNUM,args->phnum);AUXARGS_ENTRY(pos,AT_PAGESZ,args->pagesz);AUXARGS_ENTRY(pos,AT_FLAGS,args->flags);AUXARGS_ENTRY(pos,AT_ENTRY,args->entry);AUXARGS_ENTRY(pos,AT_BASE,args->base);AUXARGS_ENTRY(pos,AT_NULL,0);free(imgp->auxargs,M_TEMP);imgp->auxargs=NULL;
(*stack_base)--;suword(*stack_base,(long)imgp->argc);return0;}/**CodeforgeneratingELFcoredumps.*/typedefvoid(*segment_callback)__P((vm_map_entry_t,void*));/*Closureforcb_put_phdr().*/structphdr_closure{Elf_Phdr*phdr;/*Programheadertofillin*/Elf_Offoffset;/*Offsetofsegmentincorefile*/};/*Closureforcb_size_segment().*/structsseg_closure{intcount;/*Countofwritablesegments.*/size_tsize;/*Totalsizeofallwritablesegments.*/};staticvoidcb_put_phdr__P((vm
_map_entry_t,void*));staticvoidcb_size_segment__P((vm_map_entry_t,void*));staticvoideach_writable_segment__P((structproc*,segment_callback,void*));staticintelf_corehdr__P((structproc*,structvnode*,structucred*,int,void*,size_t));staticvoidelf_puthdr__P((structproc*,void*,size_t*,constprstatus_t*,constprfpregset_t*,constprpsinfo_t*,int));staticvoidelf_putnote__P((void*,size_t*,constchar*,int,constvoid*,size_t));externintosreldate;intelf_coredump(p
,vp,limit)registerstructproc*p;registerstructvnode*vp;off_tlimit;{registerstructucred*cred=p->p_ucred;interror=0;structsseg_closureseginfo;void*hdr;size_thdrsize;/*Sizetheprogramsegments.*/seginfo.count=0;seginfo.size=0;each_writable_segment(p,cb_size_segment,&seginfo);/**Calculatethesizeofthecorefileheaderareabymaking*adryrunofgeneratingit.Nothingiswritten,butthe*sizeiscalculated.*/hdrsize=0;elf_puthdr((structproc*)NULL,(void*)NULL,&hdrsize,(con
stprstatus_t*)NULL,(constprfpregset_t*)NULL,(constprpsinfo_t*)NULL,seginfo.count);if(hdrsize+seginfo.size>=limit)return(EFAULT);/**Allocatememoryforbuildingtheheader,fillitup,*andwriteitout.*/hdr=malloc(hdrsize,M_TEMP,M_WAITOK);if(hdr==NULL){returnEINVAL;}error=elf_corehdr(p,vp,cred,seginfo.count,hdr,hdrsize);/*Writethecontentsofallofthewritablesegments.*/if(error==0){Elf_Phdr*php;off_toffset;inti;php=(Elf_Phdr*)((char*)hdr+sizeof(Elf_Ehdr))+1;of
fset=hdrsize;for(i=0;i<seginfo.count;i++){error=vn_rdwr_inchunks(UIO_WRITE,vp,(caddr_t)php->p_vaddr,php->p_filesz,offset,UIO_USERSPACE,IO_UNIT|IO_DIRECT,cred,(int*)NULL,p);if(error!=0)break;offset+=php->p_filesz;php++;}}free(hdr,M_TEMP);returnerror;}/**Acallbackforeach_writable_segment()towriteoutthesegment's*programheaderentry.*/staticvoidcb_put_phdr(entry,closure)vm_map_entry_tentry;void*closure;{structphdr_closure*phc=(structphdr_closure*)clos
ure;Elf_Phdr*phdr=phc->phdr;phc->offset=round_page(phc->offset);phdr->p_type=PT_LOAD;phdr->p_offset=phc->offset;phdr->p_vaddr=entry->start;phdr->p_paddr=0;phdr->p_filesz=phdr->p_memsz=entry->end-entry->start;phdr->p_align=PAGE_SIZE;phdr->p_flags=0;if(entry->protection&VM_PROT_READ)phdr->p_flags|=PF_R;if(entry->protection&VM_PROT_WRITE)phdr->p_flags|=PF_W;if(entry->protection&VM_PROT_EXECUTE)phdr->p_flags|=PF_X;phc->offset+=phdr->p_filesz;phc->phd
r++;}/**Acallbackforeach_writable_segment()togatherinformationabout*thenumberofsegmentsandtheirtotalsize.*/staticvoidcb_size_segment(entry,closure)vm_map_entry_tentry;void*closure;{structsseg_closure*ssc=(structsseg_closure*)closure;ssc->count++;ssc->size+=entry->end-entry->start;}/**Foreachwritablesegmentintheprocess'smemorymap,callthegiven*functionwithapointertothemapentryandsomearbitrary*caller-supplieddata.*/staticvoideach_writable_segment(p,
func,closure)structproc*p;segment_callbackfunc;void*closure;{vm_map_tmap=&p->p_vmspace->vm_map;vm_map_entry_tentry;for(entry=map->header.next;entry!=&map->header;entry=entry->next){vm_object_tobj;if((entry->eflags&MAP_ENTRY_IS_SUB_MAP)||(entry->protection&(VM_PROT_READ|VM_PROT_WRITE))!=(VM_PROT_READ|VM_PROT_WRITE))continue;/***Dontincludememorysegmentinthecoredumpif**MAP_NOCOREissetinmmap(2)orMADV_NOCOREin**madvise(2).*/if(entry->eflags&MAP_ENTRY
_NOCOREDUMP)continue;if((obj=entry->object.vm_object)==NULL)continue;/*Findthedeepestbackingobject.*/while(obj->backing_object!=NULL)obj=obj->backing_object;/*Ignorememory-mappeddevicesandsuchthings.*/if(obj->type!=OBJT_DEFAULT&&obj->type!=OBJT_SWAP&&obj->type!=OBJT_VNODE)continue;(*func)(entry,closure);}}/**Writethecorefileheadertothefile,includingpaddingupto*thepageboundary.*/staticintelf_corehdr(p,vp,cred,numsegs,hdr,hdrsize)structproc*p;struc
tvnode*vp;structucred*cred;intnumsegs;size_thdrsize;void*hdr;{struct{prstatus_tstatus;prfpregset_tfpregset;prpsinfo_tpsinfo;}*tempdata;size_toff;prstatus_t*status;prfpregset_t*fpregset;prpsinfo_t*psinfo;tempdata=malloc(sizeof(*tempdata),M_TEMP,M_ZERO|M_WAITOK);status=&tempdata->status;fpregset=&tempdata->fpregset;psinfo=&tempdata->psinfo;/*Gathertheinformationfortheheader.*/status->pr_version=PRSTATUS_VERSION;status->pr_statussz=sizeof(prstatus_t
);status->pr_gregsetsz=sizeof(gregset_t);status->pr_fpregsetsz=sizeof(fpregset_t);status->pr_osreldate=osreldate;status->pr_cursig=p->p_sig;status->pr_pid=p->p_pid;fill_regs(p,&status->pr_reg);fill_fpregs(p,fpregset);psinfo->pr_version=PRPSINFO_VERSION;psinfo->pr_psinfosz=sizeof(prpsinfo_t);strncpy(psinfo->pr_fname,p->p_comm,sizeof(psinfo->pr_fname)-1);/*XXX-Wedon'tfillinthecommandlineargumentsproperlyyet.*/strncpy(psinfo->pr_psargs,p->p_comm,PRA
RGSZ);/*Fillintheheader.*/bzero(hdr,hdrsize);off=0;elf_puthdr(p,hdr,&off,status,fpregset,psinfo,numsegs);free(tempdata,M_TEMP);/*Writeittothecorefile.*/returnvn_rdwr_inchunks(UIO_WRITE,vp,hdr,hdrsize,(off_t)0,UIO_SYSSPACE,IO_UNIT|IO_DIRECT,cred,NULL,p);}staticvoidelf_puthdr(structproc*p,void*dst,size_t*off,constprstatus_t*status,constprfpregset_t*fpregset,constprpsinfo_t*psinfo,intnumsegs){size_tehoff;size_tphoff;size_tnoteoff;size_tnotesz;ehoff=
*off;*off+=sizeof(Elf_Ehdr);phoff=*off;*off+=(numsegs+1)*sizeof(Elf_Phdr);noteoff=*off;elf_putnote(dst,off,"FreeBSD",NT_PRSTATUS,status,sizeof*status);elf_putnote(dst,off,"FreeBSD",NT_FPREGSET,fpregset,sizeof*fpregset);elf_putnote(dst,off,"FreeBSD",NT_PRPSINFO,psinfo,sizeof*psinfo);notesz=*off-noteoff;/*Alignuptoapageboundaryfortheprogramsegments.*/*off=round_page(*off);if(dst!=NULL){Elf_Ehdr*ehdr;Elf_Phdr*phdr;structphdr_closurephc;/**FillintheE
LFheader.*/ehdr=(Elf_Ehdr*)((char*)dst+ehoff);ehdr->e_ident[EI_MAG0]=ELFMAG0;ehdr->e_ident[EI_MAG1]=ELFMAG1;ehdr->e_ident[EI_MAG2]=ELFMAG2;ehdr->e_ident[EI_MAG3]=ELFMAG3;ehdr->e_ident[EI_CLASS]=ELF_CLASS;ehdr->e_ident[EI_DATA]=ELF_DATA;ehdr->e_ident[EI_VERSION]=EV_CURRENT;ehdr->e_ident[EI_OSABI]=ELFOSABI_FREEBSD;ehdr->e_ident[EI_ABIVERSION]=0;ehdr->e_ident[EI_PAD]=0;ehdr->e_type=ET_CORE;ehdr->e_machine=ELF_ARCH;ehdr->e_version=EV_CURRENT;ehdr->e_
entry=0;ehdr->e_phoff=phoff;ehdr->e_flags=0;ehdr->e_ehsize=sizeof(Elf_Ehdr);ehdr->e_phentsize=sizeof(Elf_Phdr);ehdr->e_phnum=numsegs+1;ehdr->e_shentsize=sizeof(Elf_Shdr);ehdr->e_shnum=0;ehdr->e_shstrndx=SHN_UNDEF;/**Fillintheprogramheaderentries.*/phdr=(Elf_Phdr*)((char*)dst+phoff);/*Thenotesegement.*/phdr->p_type=PT_NOTE;phdr->p_offset=noteoff;phdr->p_vaddr=0;phdr->p_paddr=0;phdr->p_filesz=notesz;phdr->p_memsz=0;phdr->p_flags=0;phdr->p_align=0;p
hdr++;/*Allthewritablesegmentsfromtheprogram.*/phc.phdr=phdr;phc.offset=*off;each_writable_segment(p,cb_put_phdr,&phc);}}staticvoidelf_putnote(void*dst,size_t*off,constchar*name,inttype,constvoid*desc,size_tdescsz){Elf_Notenote;note.n_namesz=strlen(name)+1;note.n_descsz=descsz;note.n_type=type;if(dst!=NULL)bcopy(&note,(char*)dst+*off,sizeofnote);*off+=sizeofnote;if(dst!=NULL)bcopy(name,(char*)dst+*off,note.n_namesz);*off+=roundup2(note.n_namesz,s
izeof(Elf_Size));if(dst!=NULL)bcopy(desc,(char*)dst+*off,note.n_descsz);*off+=roundup2(note.n_descsz,sizeof(Elf_Size));}/**Tellkern_execve.caboutit,withalittlehelpfromthelinker.*/staticstructexecswelf_execsw={exec_elf_imgact,"ELF"};EXEC_SET(elf,elf_execsw);/**----------------------------------------------------------------------------*"THEBEER-WARELICENSE"(Revision42):*<phk@login.dkuug.dk>wrotethisfile.Aslongasyouretainthisnoticeyou*candowhatever
youwantwiththisstuff.Ifwemeetsomeday,andyouthink*thisstuffisworthit,youcanbuymeabeerinreturn.Poul-HenningKamp*----------------------------------------------------------------------------**$FreeBSD:src/sys/kern/imgact_gzip.c,v1.40.2.12001/11/0301:41:08psExp$**Thismodulehandlesexecutionofa.outfileswhichhavebeenrunthrough*"gzip".Thissavesdiskspace,butwastescpu-cyclesandVM.**TODO:*text-segmentsshouldbemadeR/Oafterbeingfilled*isthevm-stuffsafe?*should
handletheentireheaderofgzip'edstuff.*inflateisn'tquitereentrantyet...*error-handlingisamess...*soistherest...*tidyupunnecesaryincludes*/#include<sys/param.h>#include<sys/exec.h>#include<sys/imgact.h>#include<sys/imgact_aout.h>#include<sys/kernel.h>#include<sys/mman.h>#include<sys/proc.h>#include<sys/resourcevar.h>#include<sys/sysent.h>#include<sys/systm.h>#include<sys/vnode.h>#include<sys/inflate.h>#include<vm/vm.h>#include<vm/vm_param.h>#include
<sys/lock.h>#include<vm/pmap.h>#include<vm/vm_map.h>#include<vm/vm_kern.h>#include<vm/vm_extern.h>structimgact_gzip{structimage_params*ip;structexeca_out;interror;intgotheader;intwhere;u_char*inbuf;u_longoffset;u_longoutput;u_longlen;intidx;u_longvirtual_offset,file_offset,file_end,bss_size;};staticintexec_gzip_imgact__P((structimage_params*imgp));staticintNextByte__P((void*vp));staticintdo_aout_hdr__P((structimgact_gzip*));staticintFlush__P((voi
d*vp,u_char*,u_longsiz));staticintexec_gzip_imgact(imgp)structimage_params*imgp;{interror,error2=0;constu_char*p=(constu_char*)imgp->image_header;structimgact_gzipigz;structinflateinfl;structvmspace*vmspace;/*IfthesefourarenotOK,itisn'tagzipfile*/if(p[0]!=0x1f)return-1;/*0Simplymagic*/if(p[1]!=0x8b)return-1;/*1Simplymagic*/if(p[2]!=0x08)return-1;/*2Compressionmethod*/if(p[9]!=0x03)return-1;/*9OScompressedon*//**Ifthisonecontainsanythingbutacommen
torafilenamemarker,*wedon'twanttochewonit*/if(p[3]&~(0x18))returnENOEXEC;/*3Flags*//*Theseareofnousetous*//*4-7Timestamp*//*8Extraflags*/bzero(&igz,sizeofigz);bzero(&infl,sizeofinfl);infl.gz_private=(void*)&igz;infl.gz_input=NextByte;infl.gz_output=Flush;igz.ip=imgp;igz.idx=10;if(p[3]&0x08){/*skipafilename*/while(p[igz.idx++])if(igz.idx>=PAGE_SIZE)returnENOEXEC;}if(p[3]&0x10){/*skipacomment*/while(p[igz.idx++])if(igz.idx>=PAGE_SIZE)returnENOEXEC;
}igz.len=imgp->attr->va_size;error=inflate(&infl);/**Theunzippedfilemaynotevenhavebeenlongenoughtocontain*aheadergivingFlush()achancetoreturnerror.Checkforthis.*/if(!igz.gotheader)returnENOEXEC;if(!error){vmspace=imgp->proc->p_vmspace;error=vm_map_protect(&vmspace->vm_map,(vm_offset_t)vmspace->vm_taddr,(vm_offset_t)(vmspace->vm_taddr+(vmspace->vm_tsize<<PAGE_SHIFT)),VM_PROT_READ|VM_PROT_EXECUTE,0);}if(igz.inbuf){error2=vm_map_remove(kernel_map,(v
m_offset_t)igz.inbuf,(vm_offset_t)igz.inbuf+PAGE_SIZE);}if(igz.error||error||error2){printf("Output=%lu",igz.output);printf("Inflate_error=%digz.error=%derror2=%dwhere=%d\n",error,igz.error,error2,igz.where);}if(igz.error)returnigz.error;if(error)returnENOEXEC;if(error2)returnerror2;return0;}staticintdo_aout_hdr(structimgact_gzip*gz){interror;structvmspace*vmspace;vm_offset_tvmaddr;/**Setfile/virtualoffsetbasedona.outvariant.Wedotwocases:*hostbyt
eorderandnetworkbyteorder(forNetBSDcompatibility)*/switch((int)(gz->a_out.a_magic&0xffff)){caseZMAGIC:gz->virtual_offset=0;if(gz->a_out.a_text){gz->file_offset=PAGE_SIZE;}else{/*Bill's"screwballmode"*/gz->file_offset=0;}break;caseQMAGIC:gz->virtual_offset=PAGE_SIZE;gz->file_offset=0;break;default:/*NetBSDcompatibility*/switch((int)(ntohl(gz->a_out.a_magic)&0xffff)){caseZMAGIC:caseQMAGIC:gz->virtual_offset=PAGE_SIZE;gz->file_offset=0;break;default
:gz->where=__LINE__;return(-1);}}gz->bss_size=roundup(gz->a_out.a_bss,PAGE_SIZE);/**Checkvariousfieldsinheaderforvalidity/bounds.*/if(/*entrypointmustlaywithtextregion*/gz->a_out.a_entry<gz->virtual_offset||gz->a_out.a_entry>=gz->virtual_offset+gz->a_out.a_text||/*textanddatasizemusteachbepagerounded*/gz->a_out.a_text&PAGE_MASK||gz->a_out.a_data&PAGE_MASK){gz->where=__LINE__;return(-1);}/**text/data/bssmustnotexceedlimits*/if(/*textcan'texceedmax
imumtextsize*/gz->a_out.a_text>maxtsiz||/*data+bsscan'texceedrlimit*/gz->a_out.a_data+gz->bss_size>gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur){gz->where=__LINE__;return(ENOMEM);}/*Findouthowfarweshouldgo*/gz->file_end=gz->file_offset+gz->a_out.a_text+gz->a_out.a_data;/*copyinargumentsand/orenvironmentfromoldprocess*/error=exec_extract_strings(gz->ip);if(error){gz->where=__LINE__;return(error);}/**DestroyoldprocessVMandcreateanewone(withanewstac
k)*/exec_new_vmspace(gz->ip);vmspace=gz->ip->proc->p_vmspace;vmaddr=gz->virtual_offset;error=vm_mmap(&vmspace->vm_map,&vmaddr,gz->a_out.a_text+gz->a_out.a_data,VM_PROT_ALL,VM_PROT_ALL,MAP_ANON|MAP_FIXED,0,0);if(error){gz->where=__LINE__;return(error);}if(gz->bss_size!=0){/**Allocatedemand-zeroedareaforuninitializeddata.*"bss"='blockstartedbysymbol'-namedafterthe*IBM7090instructionofthesamename.*/vmaddr=gz->virtual_offset+gz->a_out.a_text+gz->a_ou
t.a_data;error=vm_map_find(&vmspace->vm_map,NULL,0,&vmaddr,gz->bss_size,FALSE,VM_PROT_ALL,VM_PROT_ALL,0);if(error){gz->where=__LINE__;return(error);}}/*FillinprocessVMinformation*/vmspace->vm_tsize=gz->a_out.a_text>>PAGE_SHIFT;vmspace->vm_dsize=(gz->a_out.a_data+gz->bss_size)>>PAGE_SHIFT;vmspace->vm_taddr=(caddr_t)(uintptr_t)gz->virtual_offset;vmspace->vm_daddr=(caddr_t)(uintptr_t)(gz->virtual_offset+gz->a_out.a_text);/*Fillinimage_params*/gz->ip
->interpreted=0;gz->ip->entry_addr=gz->a_out.a_entry;gz->ip->proc->p_sysent=&aout_sysvec;return0;}staticintNextByte(void*vp){interror;structimgact_gzip*igz=(structimgact_gzip*)vp;if(igz->idx>=igz->len){igz->where=__LINE__;returnGZ_EOF;}if(igz->inbuf&&igz->idx<(igz->offset+PAGE_SIZE)){returnigz->inbuf[(igz->idx++)-igz->offset];}if(igz->inbuf){error=vm_map_remove(kernel_map,(vm_offset_t)igz->inbuf,(vm_offset_t)igz->inbuf+PAGE_SIZE);if(error){igz->w
here=__LINE__;igz->error=error;returnGZ_EOF;}}igz->offset=igz->idx&~PAGE_MASK;error=vm_mmap(kernel_map,/*map*/(vm_offset_t*)&igz->inbuf,/*address*/PAGE_SIZE,/*size*/VM_PROT_READ,/*protection*/VM_PROT_READ,/*maxprotection*/0,/*flags*/(caddr_t)igz->ip->vp,/*vnode*/igz->offset);/*offset*/if(error){igz->where=__LINE__;igz->error=error;returnGZ_EOF;}returnigz->inbuf[(igz->idx++)-igz->offset];}staticintFlush(void*vp,u_char*ptr,u_longsiz){structimgact_g
zip*gz=(structimgact_gzip*)vp;u_char*p=ptr,*q;inti;/*First,findaa.out-header*/if(gz->output<sizeofgz->a_out){q=(u_char*)&gz->a_out;i=min(siz,sizeofgz->a_out-gz->output);bcopy(p,q+gz->output,i);gz->output+=i;p+=i;siz-=i;if(gz->output==sizeofgz->a_out){gz->gotheader=1;i=do_aout_hdr(gz);if(i==-1){if(!gz->where)gz->where=__LINE__;gz->error=ENOEXEC;returnENOEXEC;}elseif(i){gz->where=__LINE__;gz->error=i;returnENOEXEC;}if(gz->file_offset==0){q=(u_char*
)(uintptr_t)gz->virtual_offset;copyout(&gz->a_out,q,sizeofgz->a_out);}}}/*Skipoverzero-paddedfirstPAGEifneeded*/if(gz->output<gz->file_offset&&gz->output+siz>gz->file_offset){i=min(siz,gz->file_offset-gz->output);gz->output+=i;p+=i;siz-=i;}if(gz->output>=gz->file_offset&&gz->output<gz->file_end){i=min(siz,gz->file_end-gz->output);q=(u_char*)(uintptr_t)(gz->virtual_offset+gz->output-gz->file_offset);copyout(p,q,i);gz->output+=i;p+=i;siz-=i;}gz->ou
tput+=siz;return0;}/**Tellkern_execve.caboutit,withalittlehelpfromthelinker.*/staticstructexecswgzip_execsw={exec_gzip_imgact,"gzip"};EXEC_SET(execgzip,gzip_execsw);/**Copyright(c)1993,DavidGreenman*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclai
mer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIR
ECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/sys/kern/imgact_shell.c,v1.21.2.22001/12/2201:21:39jwdExp$*/#inclu
de<sys/param.h>#include<sys/systm.h>#include<sys/sysproto.h>#include<sys/exec.h>#include<sys/imgact.h>#include<sys/kernel.h>#ifBYTE_ORDER==LITTLE_ENDIAN#defineSHELLMAGIC0x2123/*#!*/#else#defineSHELLMAGIC0x2321#endif/**Shellinterpreterimageactivator.Ainterpreternamebeginning*atimgp->stringbaseistheminimalsuccessfulexitrequirement.*/intexec_shell_imgact(imgp)structimage_params*imgp;{constchar*image_header=imgp->image_header;constchar*ihp,*line_endp
;char*interp;/*ashellscript?*/if(((constshort*)image_header)[0]!=SHELLMAGIC)return(-1);/**Don'tallowashellscripttobetheshellforashell*script.:-)*/if(imgp->interpreted)return(ENOEXEC);imgp->interpreted=1;/**Copyshellnameandargumentsfromimage_headerintostring*buffer.*//**Findendofline;returniftheline>MAXSHELLCMDLENlong.*/for(ihp=&image_header[2];*ihp!='\n'&&*ihp!='#';++ihp){if(ihp>=&image_header[MAXSHELLCMDLEN])return(ENAMETOOLONG);}line_endp=ihp;/
*resetforanotherpass*/ihp=&image_header[2];/*Skipoverleadingspaces-untiltheinterpretername*/while((*ihp=='')||(*ihp=='\t'))ihp++;/*copytheinterpretername*/interp=imgp->interpreter_name;while((ihp<line_endp)&&(*ihp!='')&&(*ihp!='\t'))*interp++=*ihp++;*interp='\0';/*Disallowanullinterpreterfilename*/if(*imgp->interpreter_name=='\0')return(ENOEXEC);/*resetforanotherpass*/ihp=&image_header[2];/*copytheinterpreternameandarguments*/while(ihp<line_endp)
{/*Skipoverleadingspaces*/while((*ihp=='')||(*ihp=='\t'))ihp++;if(ihp<line_endp){/**Copytoendoftoken.Noneedtowatchstringspace*becausethisisatthefrontofthestringbuffer*andthemaximumshellcommandlengthistiny.*/while((ihp<line_endp)&&(*ihp!='')&&(*ihp!='\t')){*imgp->stringp++=*ihp++;imgp->stringspace--;}*imgp->stringp++=0;imgp->stringspace--;imgp->argc++;}}imgp->argv0=imgp->uap->fname;return(0);}/**Tellkern_execve.caboutit,withalittlehelpfromthelinke
r.*/staticstructexecswshell_execsw={exec_shell_imgact,"#!"};EXEC_SET(shell,shell_execsw);/**Mostpartsofthisfilearenotcoveredby:*----------------------------------------------------------------------------*"THEBEER-WARELICENSE"(Revision42):*<phk@login.dknet.dk>wrotethisfile.Aslongasyouretainthisnoticeyou*candowhateveryouwantwiththisstuff.Ifwemeetsomeday,andyouthink*thisstuffisworthit,youcanbuymeabeerinreturn.Poul-HenningKamp*----------------------
------------------------------------------------------**$FreeBSD:src/sys/kern/inflate.c,v1.141999/12/2904:54:39peterExp$***/#include<sys/param.h>#include<sys/inflate.h>#ifdef_KERNEL#include<sys/systm.h>#include<sys/kernel.h>#endif#include<sys/malloc.h>#ifdef_KERNELstaticMALLOC_DEFINE(M_GZIP,"Gziptrees","Gziptrees");#endif/*neededtomakeinflate()work*/#defineuchu_char#defineushu_short#defineulgu_long/*Stufftomakeinflate()work*/#ifdef_KERNEL#definem
emzero(dest,len)bzero(dest,len)#endif#defineNOMEMCPY#ifdef_KERNEL#defineFPRINTFprintf#elseexternvoidputstr(char*);#defineFPRINTFputstr#endif#defineFLUSH(x,y){\intfoo=(*x->gz_output)(x->gz_private,x->gz_slide,y);\if(foo)\returnfoo;\}staticconstintqflag=0;#ifndef_KERNEL/*wanttousethisfileinkzipalso*/externunsignedchar*kzipmalloc(int);externvoidkzipfree(void*);#definemalloc(x,y,z)kzipmalloc((x))#definefree(x,y)kzipfree((x))#endif/**Thiscamefromunzip
-5.12.Ihavechangedittheflowtopass*astructurepointeraround,thushopefullymakingitre-entrant.*Poul-Henning*//*inflate.c--putinthepublicdomainbyMarkAdlerversionc14o,23August1994*//*Youcandowhateveryoulikewiththissourcefile,thoughIwouldpreferthatifyoumodifyitandredistributeitthatyouincludecommentstothateffectwithyournameandthedate.Thankyou.History:versdatewhowhat---------------------------------------------------------------a~~Feb92M.Adlerusedfull(lar
ge,one-step)lookuptableb121Mar92M.Adlerfirstversionwithpartiallookuptablesb221Mar92M.Adlerfixedbuginfixed-codeblocksb322Mar92M.Adlerspedupmatchcopies,cleanedupsomeb425Mar92M.Adleraddedprototypes;removedwindow[](nowistheresponsibilityofunzip.h--alsochangednametoslide[]),soneedsdiffsforunzip.candunzip.h(thisallowscompilinginthesmallmodelonMSDOS);fixedcastofqinhuft_build();b526Mar92M.Adlergotridofunintendedmacrorecursion.b627Mar92M.Adlergotridofnext
byte()routine.fixedbugininflate_fixed().c130Mar92M.Adlerremovedlbits,dbitsenvironmentvariables.changedBMAXto16forexplode.RemovedOUTBusage,andreplaceditwithflush()--thiswasa20%speedimprovement!Addedanexplode.c(toreplaceunimplod.c)thatusesthehuftroutineshere.Removedregisterunion.c24Apr92M.Adlerfixedbugforfilesizesamultipleof32k.c310Apr92M.Adlerreducedmemoryofcodetablesmadebyhuft_buildsignificantly(factoroftwotothree).c415Apr92M.AdleraddedNOMEMCPYdo
killuseofmemcpy().workedaroundaTurboCoptimizationbug.c521Apr92M.AdleraddedtheGZ_WSIZE#definetoallowreducingthe32Kwindowsizeforspecializedapplications.c631May92M.Adleraddedsometypecaststoeliminatewarningsc727Jun92G.Roelofsaddedsomemoretypecasts(444:MSCbug).c85Oct92J-l.Gaillyaddedifdef'dcodetodealwithPKZIPbug.c99Oct92M.Adlerremovedamemoryerrormessage(~line416).c1017Oct92G.RoelofschangedULONG/UWORD/bytetoulg/ush/uch,removedoldinflate,renamedinflate_
entrytoinflate,addedMark'sfixtoacomment.c10.514Dec92M.Adlerfixuperrormessagesforincompletetrees.c112Jan93M.Adlerfixedbugindetectionofincompletetables,andremovedassumptionthatEOBisthelongestcode(badassumption).c123Jan93M.Adlermaketablesforfixedblocksonlyonce.c135Jan93M.Adlerallowallzerolengthcodes(pkzip2.04coutputsonezerolengthcodeforanemptydistancetree).c1412Mar93M.Adlermadeinflate.cstandalonewiththeintroductionofinflate.h.c14b16Jul93G.Roelofsadd
ed(unsigned)typecasttowat470.c14c19Jul93J.Bushchangedv[N_MAX],l[288],ll[28x+3x]arraystostaticforAmiga.c14d13Aug93J-l.Gaillyde-complicatifiedMark'sc[*p++]++thing.c14e8Oct93G.Roelofschangedmemset()tomemzero().c14f22Oct93G.Roelofsrenamedquietflgtoqflag;madeTrace()conditional;addedinflate_free().c14g28Oct93G.Roelofschangedl/(lx+1)macrotopointer(Craybug)c14h7Dec93C.Ghislerhuft_build()optimizations.c14i9Jan94A.Verheijensetfixed_t{d,l}toNULLafterfreeing
;G.RoelofscheckNEXTBYTEmacroforGZ_EOF.c14j23Jan94G.RoelofsremovedGhisler"optimizations";ifdef'dGZ_EOFcheck.c14k27Feb94G.Roelofsaddedsometypecaststoavoidwarnings.c14l9Apr94G.RoelofsfixedsplitcommentsonpreprocessorlinestoavoidbuginEncorecompiler.c14m7Jul94P.Kienitzmodifiedtoallowassemblerversionofinflate_codes()(defineASM_INFLATECODES)c14n22Jul94G.RoelofschangedfprintftoFPRINTFforDLLversionsc14o23Aug94C.Spieleraddedanewlinetoadebugstatement;G.Roelo
fsaddedanothertypecasttoavoidMSCwarning*//*Inflatedeflated(PKZIP'smethod8compressed)data.Thecompressionmethodsearchesforasmuchofthecurrentstringofbytes(uptoalengthof258)intheprevious32Kbytes.Ifitdoesn'tfindanymatches(ofatleastlength3),itcodesthenextbyte.Otherwise,itcodesthelengthofthematchedstringanditsdistancebackwardsfromthecurrentposition.ThereisasingleHuffmancodethatcodesbothsinglebytes(called"literals")andmatchlengths.AsecondHuffmancodecodes
thedistanceinformation,whichfollowsalengthcode.Eachlengthordistancecodeactuallyrepresentsabasevalueandanumberof"extra"(sometimeszero)bitstogettoaddtothebasevalue.Attheendofeachdeflatedblockisaspecialend-of-block(EOB)literal/lengthcode.Thedecodingprocessisbasically:getaliteral/lengthcode;ifEOBthendone;ifaliteral,emitthedecodedbyte;ifalengththengetthedistanceandemitthereferred-tobytesfromtheslidingwindowofpreviouslyemitteddata.Thereare(currently)th
reekindsofinflateblocks:stored,fixed,anddynamic.Thecompressoroutputsachunkofdataatatimeanddecideswhichmethodtouseonachunk-by-chunkbasis.Achunkmighttypicallybe32Kto64K,uncompressed.Ifthechunkisuncompressible,thenthe"stored"methodisused.Inthiscase,thebytesaresimplystoredasis,eightbitsperbyte,withnoneoftheabovecoding.Thebytesareprecededbyacount,sincethereisnolongeranEOBcode.Ifthedataiscompressible,theneitherthefixedordynamicmethodsareused.Inthedynam
icmethod,thecompresseddataisprecededbyanencodingoftheliteral/lengthanddistanceHuffmancodesthataretobeusedtodecodethisblock.TherepresentationisitselfHuffmancoded,andsoisprecededbyadescriptionofthatcode.Thesecodedescriptionstakeupalittlespace,andsoforsmallblocks,thereisapredefinedsetofcodes,calledthefixedcodes.Thefixedmethodisusediftheblockendsupsmallerthatway(usuallyforquitesmallchunks);otherwisethedynamicmethodisused.Inthelattercase,thecodesarecu
stomizedtotheprobabilitiesinthecurrentblockandsocancodeitmuchbetterthanthepre-determinedfixedcodescan.TheHuffmancodesthemselvesaredecodedusingamutli-leveltablelookup,inordertomaximizethespeedofdecodingplusthespeedofbuildingthedecodingtables.Seethecommentsbelowthatprecedethelbitsanddbitstuningparameters.*//*Notesbeyondthe1.93aappnote.txt:1.Distancepointersneverpointbeforethebeginningoftheoutputstream.2.Distancepointerscanpointbackacrossblocks,upto
32kaway.3.Thereisanimpliedmaximumof7bitsforthebitlengthtableand15bitsfortheactualdata.4.Ifonlyonecodeexists,thenitisencodedusingonebit.(Zerowouldbemoreefficient,butperhapsalittleconfusing.)Iftwocodesexist,theyarecodedusingonebiteach(0and1).5.Thereisnowayofsendingzerodistancecodes--adummymustbesentiftherearenone.(History:apre2.0versionofPKZIPwouldstoreblockswithnodistancecodes,butthiswasdiscoveredtobetooharshacriterion.)Validonlyfor1.93a.2.04cdoes
allowzerodistancecodes,whichissentasonecodeofzerobitsinlength.6.Thereareupto286literal/lengthcodes.Code256representstheend-of-block.Notehoweverthatthestaticlengthtreedefines288codesjusttofillouttheHuffmancodes.Codes286and287cannotbeusedthough,sincethereisnolengthbaseorextrabitsdefinedforthem.Similarily,thereareupto30distancecodes.However,statictreesdefine32codes(all5bits)tofillouttheHuffmancodes,butthelasttwohadbetternotshowupinthedata.7.Unzipcan
checkdynamicHuffmanblocksforcompletecodesets.Theexceptionisthatasinglecodewouldnotbecomplete(see#4).8.Thefivebitsfollowingtheblocktypeisreallythenumberofliteralcodessentminus257.9.Lengthcodes8,16,16areinterpretedas13lengthcodesof8bits(1+6+6).Therefore,tooutputthreetimesthelength,yououtputthreecodes(1+1+1),whereastooutputfourtimesthesamelength,youonlyneedtwocodes(1+3).Hmm.10.Inthetreereconstructionalgorithm,Code=Code+IncrementonlyifBitLength(i)isn
otzero.(Prettyobvious.)11.Correction:4Bits:#ofBitLengthcodes-4(4-19)12.Note:lengthcode284canrepresent227-258,butlengthcode285reallyis258.Thelastlengthdeservesitsown,shortcodesinceitgetsusedalotinveryredundantfiles.Thelength258isspecialsince258-3(theminmatchlength)is255.13.Theliteral/lengthanddistancecodebitlengthsarereadasasinglestreamoflengths.Itispossible(andadvantageous)forarepeatcode(16,17,or18)togoacrosstheboundarybetweenthetwosetsoflengths.
*/#definePKZIP_BUG_WORKAROUND/*PKZIP1.93aproblem--livewithit*//*inflate.hmustsupplytheuchslide[GZ_WSIZE]arrayandtheNEXTBYTE,FLUSH()andmemzeromacros.Ifthewindowsizeisnot32K,itshouldalsodefineGZ_WSIZE.IfINFMODisdefined,itcanincludecompiledfunctionstosupporttheNEXTBYTEand/orFLUSH()macros.TherearedefaultsforNEXTBYTEandFLUSH()belowforuseasexamplesofwhatthosefunctionsneedtodo.Normally,youwouldalsowantFLUSH()tocomputeacrconthedata.inflate.halsoneedstopr
ovidethesetypedefs:typedefunsignedcharuch;typedefunsignedshortush;typedefunsignedlongulg;Thismoduleusestheexternalfunctionsmalloc()andfree()(andprobablymemset()orbzero()inthememzero()macro).Theirprototypesarenormallyfoundin<string.h>and<stdlib.h>.*/#defineINFMOD/*tellinflate.htoincludecodetobe*compiled*//*Huffmancodelookuptableentry--thisentryisfourbytesformachinesthathave16-bitpointers(e.g.PC'sinthesmallormediummodel).Validextrabitsare0..13.e==1
5isEOB(endofblock),e==16meansthatvisaliteral,16<e<32meansthatvisapointertothenexttable,whichcodese-16bits,andlastlye==99indicatesanunusedcode.Ifacodewithe==99islookedup,thisimpliesanerrorinthedata.*/structhuft{uche;/*numberofextrabitsoroperation*/uchb;/*numberofbitsinthiscodeorsubcode*/union{ushn;/*literal,lengthbase,ordistance*base*/structhuft*t;/*pointertonextleveloftable*/}v;};/*Functionprototypes*/staticinthuft_build__P((structinflate*,unsign
ed*,unsigned,unsigned,constush*,constush*,structhuft**,int*));staticinthuft_free__P((structinflate*,structhuft*));staticintinflate_codes__P((structinflate*,structhuft*,structhuft*,int,int));staticintinflate_stored__P((structinflate*));staticintxinflate__P((structinflate*));staticintinflate_fixed__P((structinflate*));staticintinflate_dynamic__P((structinflate*));staticintinflate_block__P((structinflate*,int*));/*Theinflatealgorithmusesasliding32Kb
ytewindowontheuncompressedstreamtofindrepeatedbytestrings.Thisisimplementedhereasacircularbuffer.Theindexisupdatedsimplybyincrementingandthenand'ingwith0x7fff(32K-1).*//*Itislefttoothermodulestosupplythe32Karea.Itisassumedtobeusableasifitweredeclared"uchslide[32768];"orasjust"uch*slide;"andthenmalloc'edinthelattercase.Thedefinitionmustbeinunzip.h,includedabove.*//*TablesfordeflatefromPKZIP'sappnote.txt.*//*Orderofthebitlengthcodelengths*/staticco
nstunsignedborder[]={16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};staticconstushcplens[]={/*Copylengthsforliteralcodes257..285*/3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0};/*note:seenote#13aboveaboutthe258inthislist.*/staticconstushcplext[]={/*Extrabitsforliteralcodes257..285*/0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99};/*99==invalid*/staticconstushcpdist[]={/*Copyoffsetsfordi
stancecodes0..29*/1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};staticconstushcpdext[]={/*Extrabitsfordistancecodes*/0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};/*And'ingwithmask[n]masksthelowernbits*/staticconstushmask[]={0x0000,0x0001,0x0003,0x0007,0x000f,0x001f,0x003f,0x007f,0x00ff,0x01ff,0x03ff,0x07ff,0x0fff,0x1fff,0x3fff,0x7fff,0xffff};/*Macrosforinfl
ate()bitpeekingandgrabbing.Theusageis:NEEDBITS(glbl,j)x=b&mask[j];DUMPBITS(j)whereNEEDBITSmakessurethatbhasatleastjbitsinit,andDUMPBITSremovesthebitsfromb.Themacrosusethevariablekforthenumberofbitsinb.Normally,bandkareregistervariablesforspeed,andareinitializedatthebeginingofaroutinethatusesthesemacrosfromaglobalbitbufferandcount.Inordertonotaskformorebitsthanthereareinthecompressedstream,theHuffmantablesareconstructedtoonlyaskforjustenoughbitsto
makeuptheend-of-blockcode(value256).Thennobytesneedtobe"returned"tothebufferattheendofthelastblock.Seethehuft_build()routine.*//**Thefollowing2wereglobalvariables.*Theyarenowfieldsoftheinflatestructure.*/#defineNEEDBITS(glbl,n){\while(k<(n)){\intc=(*glbl->gz_input)(glbl->gz_private);\if(c==GZ_EOF)\return1;\b|=((ulg)c)<<k;\k+=8;\}\}#defineDUMPBITS(n){b>>=(n);k-=(n);}/*Huffmancodedecodingisperformedusingamulti-leveltablelookup.Thefastestwaytodecode
istosimplybuildalookuptablewhosesizeisdeterminedbythelongestcode.However,thetimeittakestobuildthistablecanalsobeafactorifthedatabeingdecodedisnotverylong.Themostcommoncodesarenecessarilytheshortestcodes,sothosecodesdominatethedecodingtime,andhencethespeed.Theideaisyoucanhaveashortertablethatdecodestheshorter,moreprobablecodes,andthenpointtosubsidiarytablesforthelongercodes.Thetimeitcoststodecodethelongercodesisthentradedagainstthetimeittakestomak
elongertables.Thisresultsofthistradeareinthevariableslbitsanddbitsbelow.lbitsisthenumberofbitsthefirstleveltableforliteral/lengthcodescandecodeinonestep,anddbitsisthesamethingforthedistancecodes.Subsequenttablesarealsolessthanorequaltothosesizes.Thesevaluesmaybeadjustedeitherwhenallofthecodesareshorterthanthat,inwhichcasethelongestcodelengthinbitsisused,orwhentheshortestcodeis*longer*thantherequestedtablesize,inwhichcasethelengthoftheshortestcode
inbitsisused.Therearetwodifferentvaluesforthetwotables,sincetheycodeadifferentnumberofpossibilitieseach.Theliteral/lengthtablecodes286possiblevalues,orinaflatcode,alittleovereightbits.Thedistancetablecodes30possiblevalues,oralittlelessthanfivebits,flat.Theoptimumvaluesforspeedendupbeingaboutonebitmorethanthose,solbitsis8+1anddbitsis5+1.Theoptimumvaluesmaydifferthoughfrommachinetomachine,andpossiblyevenbetweencompilers.Yourmileagemayvary.*/staticc
onstintlbits=9;/*bitsinbaseliteral/lengthlookuptable*/staticconstintdbits=6;/*bitsinbasedistancelookuptable*//*IfBMAXneedstobelargerthan16,thenhandx[]shouldbeulg.*/#defineBMAX16/*maximumbitlengthofanycode(16for*explode)*/#defineN_MAX288/*maximumnumberofcodesinanyset*//*Givenalistofcodelengthsandamaximumtablesize,makeasetoftablestodecodethatsetofcodes.Returnzeroonsuccess,oneifthegivencodesetisincomplete(thetablesarestillbuiltinthiscase),twoifthein
putisinvalid(allzerolengthcodesoranoversubscribedsetoflengths),andthreeifnotenoughmemory.Thecodewithvalue256isspecial,andthetablesareconstructedsothatnobitsbeyondthatcodearefetchedwhenthatcodeisdecoded.*/staticinthuft_build(glbl,b,n,s,d,e,t,m)structinflate*glbl;unsigned*b;/*codelengthsinbits(allassumed<=BMAX)*/unsignedn;/*numberofcodes(assumed<=N_MAX)*/unsigneds;/*numberofsimple-valuedcodes(0..s-1)*/constush*d;/*listofbasevaluesfornon-simplecodes
*/constush*e;/*listofextrabitsfornon-simplecodes*/structhuft**t;/*result:startingtable*/int*m;/*maximumlookupbits,returnsactual*/{unsigneda;/*counterforcodesoflengthk*/unsignedc[BMAX+1];/*bitlengthcounttable*/unsignedel;/*lengthofEOBcode(value256)*/unsignedf;/*irepeatsintableeveryfentries*/intg;/*maximumcodelength*/inth;/*tablelevel*/registerunsignedi;/*counter,currentcode*/registerunsignedj;/*counter*/registerintk;/*numberofbitsincurrentcode*/in
tlx[BMAX+1];/*memoryforl[-1..BMAX-1]*/int*l=lx+1;/*stackofbitspertable*/registerunsigned*p;/*pointerintoc[],b[],orv[]*/registerstructhuft*q;/*pointstocurrenttable*/structhuftr;/*tableentryforstructureassignment*/structhuft*u[BMAX];/*tablestack*/unsignedv[N_MAX];/*valuesinorderofbitlength*/registerintw;/*bitsbeforethistable==(l*h)*/unsignedx[BMAX+1];/*bitoffsets,thencodestack*/unsigned*xp;/*pointerintox*/inty;/*numberofdummycodesadded*/unsignedz;/
*numberofentriesincurrenttable*//*Generatecountsforeachbitlength*/el=n>256?b[256]:BMAX;/*setlengthofEOBcode,ifany*/#ifdef_KERNELmemzero((char*)c,sizeof(c));#elsefor(i=0;i<BMAX+1;i++)c[i]=0;#endifp=b;i=n;do{c[*p]++;p++;/*assumeallentries<=BMAX*/}while(--i);if(c[0]==n){/*nullinput--allzerolengthcodes*/*t=(structhuft*)NULL;*m=0;return0;}/*Findminimumandmaximumlength,bound*mbythose*/for(j=1;j<=BMAX;j++)if(c[j])break;k=j;/*minimumcodelength*/if((unsig
ned)*m<j)*m=j;for(i=BMAX;i;i--)if(c[i])break;g=i;/*maximumcodelength*/if((unsigned)*m>i)*m=i;/*Adjustlastlengthcounttofilloutcodes,ifneeded*/for(y=1<<j;j<i;j++,y<<=1)if((y-=c[j])<0)return2;/*badinput:morecodesthanbits*/if((y-=c[i])<0)return2;c[i]+=y;/*Generatestartingoffsetsintothevaluetableforeachlength*/x[1]=j=0;p=c+1;xp=x+2;while(--i){/*notethati==gfromabove*/*xp++=(j+=*p++);}/*Makeatableofvaluesinorderofbitlengths*/p=b;i=0;do{if((j=*p++)!=0)v
[x[j]++]=i;}while(++i<n);/*GeneratetheHuffmancodesandforeach,makethetableentries*/x[0]=i=0;/*firstHuffmancodeiszero*/p=v;/*grabvaluesinbitorder*/h=-1;/*notablesyet--level-1*/w=l[-1]=0;/*nobitsdecodedyet*/u[0]=(structhuft*)NULL;/*justtokeepcompilershappy*/q=(structhuft*)NULL;/*ditto*/z=0;/*ditto*//*gothroughthebitlengths(kalreadyisbitsinshortestcode)*/for(;k<=g;k++){a=c[k];while(a--){/**hereiistheHuffmancodeoflengthkbitsfor*value*p*//*maketablesup
torequiredlevel*/while(k>w+l[h]){w+=l[h++];/*addbitsalreadydecoded*//**computeminimumsizetablelessthanor*equalto*mbits*/z=(z=g-w)>(unsigned)*m?*m:z;/*upperlimit*/if((f=1<<(j=k-w))>a+1){/*tryak-wbittable*//*t*oofewcodesfork-w*bittable*/f-=a+1;/*deductcodesfrom*patternsleft*/xp=c+k;while(++j<z){/*trysmallertablesup*tozbits*/if((f<<=1)<=*++xp)break;/*enoughcodestouse*upjbits*/f-=*xp;/*elsedeductcodes*frompatterns*/}}if((unsigned)w+j>el&&(unsigned)w<
el)j=el-w;/*makeEOBcodeendat*table*/z=1<<j;/*tableentriesforj-bit*table*/l[h]=j;/*settablesizeinstack*//*allocateandlinkinnewtable*/if((q=(structhuft*)malloc((z+1)*sizeof(structhuft),M_GZIP,M_WAITOK))==(structhuft*)NULL){if(h)huft_free(glbl,u[0]);return3;/*notenoughmemory*/}glbl->gz_hufts+=z+1;/*trackmemoryusage*/*t=q+1;/*linktolistfor*huft_free()*/*(t=&(q->v.t))=(structhuft*)NULL;u[h]=++q;/*tablestartsafterlink*//*connecttolasttable,ifthereisone
*/if(h){x[h]=i;/*savepatternfor*backingup*/r.b=(uch)l[h-1];/*bitstodumpbefore*thistable*/r.e=(uch)(16+j);/*bitsinthistable*/r.v.t=q;/*pointertothistable*/j=(i&((1<<w)-1))>>(w-l[h-1]);u[h-1][j]=r;/*connecttolasttable*/}}/*setuptableentryinr*/r.b=(uch)(k-w);if(p>=v+n)r.e=99;/*outofvalues--invalid*code*/elseif(*p<s){r.e=(uch)(*p<256?16:15);/*256isend-of-block*code*/r.v.n=*p++;/*simplecodeisjustthe*value*/}else{r.e=(uch)e[*p-s];/*non-simple--lookup*i
nlists*/r.v.n=d[*p++-s];}/*fillcode-likeentrieswithr*/f=1<<(k-w);for(j=i>>w;j<z;j+=f)q[j]=r;/*backwardsincrementthek-bitcodei*/for(j=1<<(k-1);i&j;j>>=1)i^=j;i^=j;/*backupoverfinishedtables*/while((i&((1<<w)-1))!=x[h])w-=l[--h];/*don'tneedtoupdateq*/}}/*returnactualsizeofbasetable*/*m=l[0];/*Returntrue(1)ifweweregivenanincompletetable*/returny!=0&&g!=1;}staticinthuft_free(glbl,t)structinflate*glbl;structhuft*t;/*tabletofree*//*Freethemalloc'edtabl
esbuiltbyhuft_build(),whichmakesalinkedlistofthetablesitmade,withthelinksinadummyfirstentryofeachtable.*/{registerstructhuft*p,*q;/*Gothroughlinkedlist,freeingfromthemalloced(t[-1])address.*/p=t;while(p!=(structhuft*)NULL){q=(--p)->v.t;free(p,M_GZIP);p=q;}return0;}/*inflate(decompress)thecodesinadeflated(compressed)block.Returnanerrorcodeorzeroifitallgoesok.*/staticintinflate_codes(glbl,tl,td,bl,bd)structinflate*glbl;structhuft*tl,*td;/*literal/l
engthanddistancedecodertables*/intbl,bd;/*numberofbitsdecodedbytl[]andtd[]*/{registerunsignede;/*tableentryflag/numberofextrabits*/unsignedn,d;/*lengthandindexforcopy*/unsignedw;/*currentwindowposition*/structhuft*t;/*pointertotableentry*/unsignedml,md;/*masksforblandbdbits*/registerulgb;/*bitbuffer*/registerunsignedk;/*numberofbitsinbitbuffer*//*makelocalcopiesofglobals*/b=glbl->gz_bb;/*initializebitbuffer*/k=glbl->gz_bk;w=glbl->gz_wp;/*initiali
zewindowposition*//*inflatethecodeddata*/ml=mask[bl];/*precomputemasksforspeed*/md=mask[bd];while(1){/*dountilendofblock*/NEEDBITS(glbl,(unsigned)bl)if((e=(t=tl+((unsigned)b&ml))->e)>16)do{if(e==99)return1;DUMPBITS(t->b)e-=16;NEEDBITS(glbl,e)}while((e=(t=t->v.t+((unsigned)b&mask[e]))->e)>16);DUMPBITS(t->b)if(e==16){/*thenit'saliteral*/glbl->gz_slide[w++]=(uch)t->v.n;if(w==GZ_WSIZE){FLUSH(glbl,w);w=0;}}else{/*it'sanEOBoralength*//*exitifendofblock
*/if(e==15)break;/*getlengthofblocktocopy*/NEEDBITS(glbl,e)n=t->v.n+((unsigned)b&mask[e]);DUMPBITS(e);/*decodedistanceofblocktocopy*/NEEDBITS(glbl,(unsigned)bd)if((e=(t=td+((unsigned)b&md))->e)>16)do{if(e==99)return1;DUMPBITS(t->b)e-=16;NEEDBITS(glbl,e)}while((e=(t=t->v.t+((unsigned)b&mask[e]))->e)>16);DUMPBITS(t->b)NEEDBITS(glbl,e)d=w-t->v.n-((unsigned)b&mask[e]);DUMPBITS(e)/*dothecopy*/do{n-=(e=(e=GZ_WSIZE-((d&=GZ_WSIZE-1)>w?d:w))>n?n:e);#ifnde
fNOMEMCPYif(w-d>=e){/*(thistestassumes*unsignedcomparison)*/memcpy(glbl->gz_slide+w,glbl->gz_slide+d,e);w+=e;d+=e;}else/*doitslowtoavoidmemcpy()*overlap*/#endif/*!NOMEMCPY*/do{glbl->gz_slide[w++]=glbl->gz_slide[d++];}while(--e);if(w==GZ_WSIZE){FLUSH(glbl,w);w=0;}}while(n);}}/*restoretheglobalsfromthelocals*/glbl->gz_wp=w;/*restoreglobalwindowpointer*/glbl->gz_bb=b;/*restoreglobalbitbuffer*/glbl->gz_bk=k;/*done*/return0;}/*"decompress"aninflatedty
pe0(stored)block.*/staticintinflate_stored(glbl)structinflate*glbl;{unsignedn;/*numberofbytesinblock*/unsignedw;/*currentwindowposition*/registerulgb;/*bitbuffer*/registerunsignedk;/*numberofbitsinbitbuffer*//*makelocalcopiesofglobals*/b=glbl->gz_bb;/*initializebitbuffer*/k=glbl->gz_bk;w=glbl->gz_wp;/*initializewindowposition*//*gotobyteboundary*/n=k&7;DUMPBITS(n);/*getthelengthanditscomplement*/NEEDBITS(glbl,16)n=((unsigned)b&0xffff);DUMPBITS(16
)NEEDBITS(glbl,16)if(n!=(unsigned)((~b)&0xffff))return1;/*errorincompresseddata*/DUMPBITS(16)/*readandoutputthecompresseddata*/while(n--){NEEDBITS(glbl,8)glbl->gz_slide[w++]=(uch)b;if(w==GZ_WSIZE){FLUSH(glbl,w);w=0;}DUMPBITS(8)}/*restoretheglobalsfromthelocals*/glbl->gz_wp=w;/*restoreglobalwindowpointer*/glbl->gz_bb=b;/*restoreglobalbitbuffer*/glbl->gz_bk=k;return0;}/*decompressaninflatedtype1(fixedHuffmancodes)block.Weshouldeitherreplacethiswith
acustomdecoder,oratleastprecomputetheHuffmantables.*/staticintinflate_fixed(glbl)structinflate*glbl;{/*iffirsttime,setuptablesforfixedblocks*/if(glbl->gz_fixed_tl==(structhuft*)NULL){inti;/*temporaryvariable*/staticunsignedl[288];/*lengthlistforhuft_build*//*literaltable*/for(i=0;i<144;i++)l[i]=8;for(;i<256;i++)l[i]=9;for(;i<280;i++)l[i]=7;for(;i<288;i++)/*makeacomplete,butwrongcode*set*/l[i]=8;glbl->gz_fixed_bl=7;if((i=huft_build(glbl,l,288,257,
cplens,cplext,&glbl->gz_fixed_tl,&glbl->gz_fixed_bl))!=0){glbl->gz_fixed_tl=(structhuft*)NULL;returni;}/*distancetable*/for(i=0;i<30;i++)/*makeanincompletecode*set*/l[i]=5;glbl->gz_fixed_bd=5;if((i=huft_build(glbl,l,30,0,cpdist,cpdext,&glbl->gz_fixed_td,&glbl->gz_fixed_bd))>1){huft_free(glbl,glbl->gz_fixed_tl);glbl->gz_fixed_tl=(structhuft*)NULL;returni;}}/*decompressuntilanend-of-blockcode*/returninflate_codes(glbl,glbl->gz_fixed_tl,glbl->gz_fix
ed_td,glbl->gz_fixed_bl,glbl->gz_fixed_bd)!=0;}/*decompressaninflatedtype2(dynamicHuffmancodes)block.*/staticintinflate_dynamic(glbl)structinflate*glbl;{inti;/*temporaryvariables*/unsignedj;unsignedl;/*lastlength*/unsignedm;/*maskforbitlengthstable*/unsignedn;/*numberoflengthstoget*/structhuft*tl;/*literal/lengthcodetable*/structhuft*td;/*distancecodetable*/intbl;/*lookupbitsfortl*/intbd;/*lookupbitsfortd*/unsignednb;/*numberofbitlengthcodes*/uns
ignednl;/*numberofliteral/lengthcodes*/unsignednd;/*numberofdistancecodes*/#ifdefPKZIP_BUG_WORKAROUNDunsignedll[288+32];/*literal/lengthanddistancecode*lengths*/#elseunsignedll[286+30];/*literal/lengthanddistancecode*lengths*/#endifregisterulgb;/*bitbuffer*/registerunsignedk;/*numberofbitsinbitbuffer*//*makelocalbitbuffer*/b=glbl->gz_bb;k=glbl->gz_bk;/*readintablelengths*/NEEDBITS(glbl,5)nl=257+((unsigned)b&0x1f);/*numberof*literal/lengthcodes*/D
UMPBITS(5)NEEDBITS(glbl,5)nd=1+((unsigned)b&0x1f);/*numberofdistancecodes*/DUMPBITS(5)NEEDBITS(glbl,4)nb=4+((unsigned)b&0xf);/*numberofbitlengthcodes*/DUMPBITS(4)#ifdefPKZIP_BUG_WORKAROUNDif(nl>288||nd>32)#elseif(nl>286||nd>30)#endifreturn1;/*badlengths*//*readinbit-length-codelengths*/for(j=0;j<nb;j++){NEEDBITS(glbl,3)ll[border[j]]=(unsigned)b&7;DUMPBITS(3)}for(;j<19;j++)ll[border[j]]=0;/*builddecodingtablefortrees--singlelevel,7bitlookup*/bl=7;
if((i=huft_build(glbl,ll,19,19,NULL,NULL,&tl,&bl))!=0){if(i==1)huft_free(glbl,tl);returni;/*incompletecodeset*/}/*readinliteralanddistancecodelengths*/n=nl+nd;m=mask[bl];i=l=0;while((unsigned)i<n){NEEDBITS(glbl,(unsigned)bl)j=(td=tl+((unsigned)b&m))->b;DUMPBITS(j)j=td->v.n;if(j<16)/*lengthofcodeinbits(0..15)*/ll[i++]=l=j;/*savelastlengthinl*/elseif(j==16){/*repeatlastlength3to6times*/NEEDBITS(glbl,2)j=3+((unsigned)b&3);DUMPBITS(2)if((unsigned)i+j
>n)return1;while(j--)ll[i++]=l;}elseif(j==17){/*3to10zerolengthcodes*/NEEDBITS(glbl,3)j=3+((unsigned)b&7);DUMPBITS(3)if((unsigned)i+j>n)return1;while(j--)ll[i++]=0;l=0;}else{/*j==18:11to138zerolengthcodes*/NEEDBITS(glbl,7)j=11+((unsigned)b&0x7f);DUMPBITS(7)if((unsigned)i+j>n)return1;while(j--)ll[i++]=0;l=0;}}/*freedecodingtablefortrees*/huft_free(glbl,tl);/*restoretheglobalbitbuffer*/glbl->gz_bb=b;glbl->gz_bk=k;/*buildthedecodingtablesforliteral/
lengthanddistancecodes*/bl=lbits;i=huft_build(glbl,ll,nl,257,cplens,cplext,&tl,&bl);if(i!=0){if(i==1&&!qflag){FPRINTF("(incompletel-tree)");huft_free(glbl,tl);}returni;/*incompletecodeset*/}bd=dbits;i=huft_build(glbl,ll+nl,nd,0,cpdist,cpdext,&td,&bd);if(i!=0){if(i==1&&!qflag){FPRINTF("(incompleted-tree)");#ifdefPKZIP_BUG_WORKAROUNDi=0;}#elsehuft_free(glbl,td);}huft_free(glbl,tl);returni;/*incompletecodeset*/#endif}/*decompressuntilanend-of-blockc
ode*/if(inflate_codes(glbl,tl,td,bl,bd))return1;/*freethedecodingtables,return*/huft_free(glbl,tl);huft_free(glbl,td);return0;}/*decompressaninflatedblock*/staticintinflate_block(glbl,e)structinflate*glbl;int*e;/*lastblockflag*/{unsignedt;/*blocktype*/registerulgb;/*bitbuffer*/registerunsignedk;/*numberofbitsinbitbuffer*//*makelocalbitbuffer*/b=glbl->gz_bb;k=glbl->gz_bk;/*readinlastblockbit*/NEEDBITS(glbl,1)*e=(int)b&1;DUMPBITS(1)/*readinblocktyp
e*/NEEDBITS(glbl,2)t=(unsigned)b&3;DUMPBITS(2)/*restoretheglobalbitbuffer*/glbl->gz_bb=b;glbl->gz_bk=k;/*inflatethatblocktype*/if(t==2)returninflate_dynamic(glbl);if(t==0)returninflate_stored(glbl);if(t==1)returninflate_fixed(glbl);/*badblocktype*/return2;}/*decompressaninflatedentry*/staticintxinflate(glbl)structinflate*glbl;{inte;/*lastblockflag*/intr;/*resultcode*/unsignedh;/*maximumstructhuft'smalloc'ed*/glbl->gz_fixed_tl=(structhuft*)NULL;/*
initializewindow,bitbuffer*/glbl->gz_wp=0;glbl->gz_bk=0;glbl->gz_bb=0;/*decompressuntilthelastblock*/h=0;do{glbl->gz_hufts=0;if((r=inflate_block(glbl,&e))!=0)returnr;if(glbl->gz_hufts>h)h=glbl->gz_hufts;}while(!e);/*flushoutslide*/FLUSH(glbl,glbl->gz_wp);/*returnsuccess*/return0;}/*Nobodyusesthis-whynot?*/intinflate(glbl)structinflate*glbl;{inti;#ifdef_KERNELu_char*p=NULL;if(!glbl->gz_slide)p=glbl->gz_slide=malloc(GZ_WSIZE,M_GZIP,M_WAITOK);#endif
if(!glbl->gz_slide)#ifdef_KERNELreturn(ENOMEM);#elsereturn3;/*kzipexpects3*/#endifi=xinflate(glbl);if(glbl->gz_fixed_td!=(structhuft*)NULL){huft_free(glbl,glbl->gz_fixed_td);glbl->gz_fixed_td=(structhuft*)NULL;}if(glbl->gz_fixed_tl!=(structhuft*)NULL){huft_free(glbl,glbl->gz_fixed_tl);glbl->gz_fixed_tl=(structhuft*)NULL;}#ifdef_KERNELif(p==glbl->gz_slide){free(glbl->gz_slide,M_GZIP);glbl->gz_slide=NULL;}#endifreturni;}/*-----------------------END
INFLATE.C*//**Copyright(c)1995TerrenceR.Lambert*Allrightsreserved.**Copyright(c)1982,1986,1989,1991,1992,1993*TheRegentsoftheUniversityofCalifornia.Allrightsreserved.*(c)UNIXSystemLaboratories,Inc.*Allorsomeportionsofthisfilearederivedfrommateriallicensed*totheUniversityofCaliforniabyAmericanTelephoneandTelegraph*Co.orUnixSystemLaboratories,Inc.andarereproducedhereinwith*thepermissionofUNIXSystemLaboratories,Inc.**Redistributionanduseinsourceandb
inaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentationand/orothermaterialsprovidedwiththedistribution.*3.Alladvertisingmaterialsmentioningfeaturesoruseofthissoftware*mus
tdisplaythefollowingacknowledgement:*ThisproductincludessoftwaredevelopedbytheUniversityof*California,Berkeleyanditscontributors.*4.NeitherthenameoftheUniversitynorthenamesofitscontributors*maybeusedtoendorseorpromoteproductsderivedfromthissoftware*withoutspecificpriorwrittenpermission.**THISSOFTWAREISPROVIDEDBYTHEREGENTSANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFIT
NESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEREGENTSORCONTRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEP
OSSIBILITYOF*SUCHDAMAGE.**@(#)init_main.c8.9(Berkeley)1/21/94*$FreeBSD:src/sys/kern/init_main.c,v1.134.2.72002/05/0122:56:08iedowseExp$*/#include"opt_init_path.h"#include<sys/param.h>#include<sys/file.h>#include<sys/filedesc.h>#include<sys/kernel.h>#include<sys/mount.h>#include<sys/sysctl.h>#include<sys/proc.h>#include<sys/resourcevar.h>#include<sys/signalvar.h>#include<sys/systm.h>#include<sys/vnode.h>#include<sys/sysent.h>#include<sys/reboot.h>
#include<sys/sysproto.h>#include<sys/vmmeter.h>#include<sys/unistd.h>#include<sys/malloc.h>#include<machine/cpu.h>#include<vm/vm.h>#include<vm/vm_param.h>#include<sys/lock.h>#include<vm/pmap.h>#include<vm/vm_map.h>#include<sys/user.h>#include<sys/copyright.h>externstructlinker_setsysinit_set;/*XXX*/voidmi_startup(void);/*Shouldbeelsewhere*//*Componentsofthefirstprocess--neverfreed.*/staticstructsessionsession0;staticstructpgrppgrp0;structprocproc
0;staticstructpcredcred0;staticstructprocsigprocsig0;staticstructfiledesc0filedesc0;staticstructplimitlimit0;staticstructvmspacevmspace0;structproc*initproc;intcmask=CMASK;externstructuser*proc0paddr;externintfallback_elf_brand;structvnode*rootvp;intboothowto=0;/*initializedsothatitcanbepatched*/SYSCTL_INT(_debug,OID_AUTO,boothowto,CTLFLAG_RD,&boothowto,0,"");/**Thisensuresthatthereisatleastoneentrysothatthesysinit_set*symbolisnotundefined.Asybsy
stemIDofSI_SUB_DUMMYisnever*executed.*/SYSINIT(placeholder,SI_SUB_DUMMY,SI_ORDER_ANY,NULL,NULL)/**Thesysinittableitself.Itemsarecheckedoffasthearerun.*Ifwewanttoregisternewsysinittypes,addthemtonewsysinit.*/structsysinit**sysinit=(structsysinit**)sysinit_set.ls_items;structsysinit**newsysinit;/**Mergeanewsysinitsetintothecurrentset,reallocatingitif*necessary.Thiscanonlybecalledaftermallocisrunning.*/voidsysinit_add(structsysinit**set){structsysin
it**newset;structsysinit**sipp;structsysinit**xipp;intcount=0;if(newsysinit)for(sipp=newsysinit;*sipp;sipp++)count++;elsefor(sipp=sysinit;*sipp;sipp++)count++;for(sipp=set;*sipp;sipp++)count++;count++;/*TrailingNULL*/newset=malloc(count*sizeof(*sipp),M_TEMP,M_NOWAIT);if(newset==NULL)panic("cannotmallocforsysinit");xipp=newset;if(newsysinit)for(sipp=newsysinit;*sipp;sipp++)*xipp++=*sipp;elsefor(sipp=sysinit;*sipp;sipp++)*xipp++=*sipp;for(sipp=set;
*sipp;sipp++)*xipp++=*sipp;*xipp=NULL;if(newsysinit)free(newsysinit,M_TEMP);newsysinit=newset;}/**Systemstartup;initializetheworld,createprocess0,mountroot*filesystem,andforktocreateinitandpagedaemon.Mostofthe*hardworkisdoneinthelower-levelinitializationroutinesincluding*startup(),whichdoesmemoryinitializationandautoconfiguration.**Thisallowssimpleadditionofnewkernelsubsystemsthatrequire*boottimeinitialization.Italsoallowssubstitutionofsubsystem*
(forinstance,ascheduler,kernelprofiler,orVMsystem)byobject*module.Finally,itallowsforoptional"kernelthreads".*/voidmi_startup(void){registerstructsysinit**sipp;/*systeminitialization*/registerstructsysinit**xipp;/*interiorloopofsort*/registerstructsysinit*save;/*bubble*/restart:/**Performabubblesortofthesysteminitializationobjectsby*theirsubsystem(primarykey)andorder(secondarykey).*/for(sipp=sysinit;*sipp;sipp++){for(xipp=sipp+1;*xipp;xipp++){if(
(*sipp)->subsystem<(*xipp)->subsystem||((*sipp)->subsystem==(*xipp)->subsystem&&(*sipp)->order<=(*xipp)->order))continue;/*skip*/save=*sipp;*sipp=*xipp;*xipp=save;}}/**Traversethe(now)orderedlistofsysteminitializationtasks.*Performeachtask,andcontinueontothenexttask.**Thelastitemonthelistisexpectedtobethescheduler,*whichwillnotreturn.*/for(sipp=sysinit;*sipp;sipp++){if((*sipp)->subsystem==SI_SUB_DUMMY)continue;/*skipdummytask(s)*/if((*sipp)->subs
ystem==SI_SUB_DONE)continue;/*Callfunction*/(*((*sipp)->func))((*sipp)->udata);/*Checkofftheonewe'rejustdone*/(*sipp)->subsystem=SI_SUB_DONE;/*Checkifwe'veinstalledmoresysinititemsviaKLD*/if(newsysinit!=NULL){if(sysinit!=(structsysinit**)sysinit_set.ls_items)free(sysinit,M_TEMP);sysinit=newsysinit;newsysinit=NULL;gotorestart;}}panic("Shouldn'tgethere!");/*NOTREACHED*/}/******************************************************************************
******ThefollowingSYSINIT'sbelongelsewhere,buthavenotyet****beenmoved.********************************************************************************/staticvoidprint_caddr_t(void*data__unused){printf("%s",(char*)data);}SYSINIT(announce,SI_SUB_COPYRIGHT,SI_ORDER_FIRST,print_caddr_t,copyright)/************************************************************************************ThetwofollowingSYSINT'sareproc0specificgluecode.Iamnot****convincedthatt
heycannotbesafelycombined,buttheirorderof****operationhasbeenmaintainedasthesameastheoriginalinit_main.c****forrightnow.********Theseprobablybelongininit_proc.corkern_proc.c,sincethey****dealwithproc0(theforktemplateprocess).********************************************************************************//*ARGSUSED*/staticvoidproc0_init(void*dummy__unused){registerstructproc*p;registerstructfiledesc0*fdp;registerunsignedi;p=&proc0;/**Initializepr
ocessandpgrpstructures.*/procinit();/**Initializesleepqueuehashtable*/sleepinit();/**additionalVMstructures*/vm_init2();/**Createprocess0(theswapper).*/LIST_INSERT_HEAD(&allproc,p,p_list);p->p_pgrp=&pgrp0;LIST_INSERT_HEAD(PGRPHASH(0),&pgrp0,pg_hash);LIST_INIT(&pgrp0.pg_members);LIST_INSERT_HEAD(&pgrp0.pg_members,p,p_pglist);pgrp0.pg_session=&session0;session0.s_count=1;session0.s_leader=p;p->p_sysent=&aout_sysvec;p->p_flag=P_INMEM|P_SYSTEM;p->p_s
tat=SRUN;p->p_nice=NZERO;p->p_rtprio.type=RTP_PRIO_NORMAL;p->p_rtprio.prio=0;p->p_peers=0;p->p_leader=p;bcopy("swapper",p->p_comm,sizeof("swapper"));/*Createcredentials.*/cred0.p_refcnt=1;cred0.p_uidinfo=uifind(0);p->p_cred=&cred0;p->p_ucred=crget();p->p_ucred->cr_ngroups=1;/*group0*/p->p_ucred->cr_uidinfo=uifind(0);/*Don'tjailit*/p->p_prison=0;/*Createprocsig.*/p->p_procsig=&procsig0;p->p_procsig->ps_refcnt=1;/*Initializesignalstateforprocess0.*
/siginit(&proc0);/*Createthefiledescriptortable.*/fdp=&filedesc0;p->p_fd=&fdp->fd_fd;fdp->fd_fd.fd_refcnt=1;fdp->fd_fd.fd_cmask=cmask;fdp->fd_fd.fd_ofiles=fdp->fd_dfiles;fdp->fd_fd.fd_ofileflags=fdp->fd_dfileflags;fdp->fd_fd.fd_nfiles=NDFILE;/*Createthelimitsstructures.*/p->p_limit=&limit0;for(i=0;i<sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]);i++)limit0.pl_rlimit[i].rlim_cur=limit0.pl_rlimit[i].rlim_max=RLIM_INFINITY;limit0.pl_rlimit[RLIMIT_NOFILE
].rlim_cur=limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max=maxfiles;limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur=limit0.pl_rlimit[RLIMIT_NPROC].rlim_max=maxproc;i=ptoa(cnt.v_free_count);limit0.pl_rlimit[RLIMIT_RSS].rlim_max=i;limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max=i;limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur=i/3;limit0.p_cpulimit=RLIM_INFINITY;limit0.p_refcnt=1;/*Allocateaprototypemapsowehavesomethingtofork.*/pmap_pinit0(vmspace_pmap(&vmspace0));p->p_vmspa
ce=&vmspace0;vmspace0.vm_refcnt=1;vm_map_init(&vmspace0.vm_map,round_page(VM_MIN_ADDRESS),trunc_page(VM_MAXUSER_ADDRESS));vmspace0.vm_map.pmap=vmspace_pmap(&vmspace0);p->p_addr=proc0paddr;/*XXX*//**Wecontinuetoplaceresourceusageinfoandsignal*actionsintheuserstructsothey'repageable.*/p->p_stats=&p->p_addr->u_stats;p->p_sigacts=&p->p_addr->u_sigacts;/**Chargerootforoneprocess.*/(void)chgproccnt(cred0.p_uidinfo,1,0);/**Initializethecurrentprocesspoi
nter(curproc)before*anypossibletraps/probestosimplifytrapprocessing.*/SET_CURPROC(p);}SYSINIT(p0init,SI_SUB_INTRINSIC,SI_ORDER_FIRST,proc0_init,NULL)/*ARGSUSED*/staticvoidproc0_post(void*dummy__unused){structtimespects;structproc*p;/**Nowwecanlookatthetime,havinghadachancetoverifythe*timefromthefilesystem.Pretendthatproc0startednow.*/LIST_FOREACH(p,&allproc,p_list){microtime(&p->p_stats->p_start);p->p_runtime=0;}microuptime(&switchtime);switchtic
ks=ticks;/**Givethe``random''numbergeneratorathump.*XXX:Doesread_random()containenoughbitstobeusedhere?*/nanotime(&ts);srandom(ts.tv_sec^ts.tv_nsec);}SYSINIT(p0post,SI_SUB_INTRINSIC_POST,SI_ORDER_FIRST,proc0_post,NULL)/************************************************************************************ThefollowingSYSINIT'sandgluecodeshouldbemovedtothe****respectivefilesonapersubsystembasis.*********************************************************
***********************//************************************************************************************Thefollowingcodeprobablybelongsinanotherfile,like****kern/init_init.c.********************************************************************************//**Listofpathstotrywhensearchingfor"init".*/staticcharinit_path[MAXPATHLEN]=#ifdefINIT_PATH__XSTRING(INIT_PATH);#else"/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall";#endifSYSCTL_ST
RING(_kern,OID_AUTO,init_path,CTLFLAG_RD,init_path,0,"");/**Starttheinitialuserprocess;tryexec'ingeachpathnameininit_path.*Theprogramisinvokedwithoneargumentcontainingthebootflags.*/staticvoidstart_init(void*dummy){vm_offset_taddr;structexecve_argsargs;intoptions,error;char*var,*path,*next,*s;char*ucp,**uap,*arg0,*arg1;structproc*p;p=curproc;/*Getthevnodefor'/'.Setp->p_fd->fd_cdirtoreferenceit.*/if(VFS_ROOT(TAILQ_FIRST(&mountlist),&rootvnode))pan
ic("cannotfindrootvnode");p->p_fd->fd_cdir=rootvnode;VREF(p->p_fd->fd_cdir);p->p_fd->fd_rdir=rootvnode;VREF(p->p_fd->fd_rdir);VOP_UNLOCK(rootvnode,0,p);/**Needjustenoughstacktoholdthefaked-up"execve()"arguments.*/addr=trunc_page(USRSTACK-PAGE_SIZE);if(vm_map_find(&p->p_vmspace->vm_map,NULL,0,&addr,PAGE_SIZE,FALSE,VM_PROT_ALL,VM_PROT_ALL,0)!=0)panic("init:couldn'tallocateargumentspace");p->p_vmspace->vm_maxsaddr=(caddr_t)addr;p->p_vmspace->vm_ssiz
e=1;if((var=getenv("init_path"))!=NULL){strncpy(init_path,var,sizeofinit_path);init_path[sizeofinit_path-1]=0;}if((var=getenv("kern.fallback_elf_brand"))!=NULL)fallback_elf_brand=strtol(var,NULL,0);for(path=init_path;*path!='\0';path=next){while(*path==':')path++;if(*path=='\0')break;for(next=path;*next!='\0'&&*next!=':';next++)/*nothing*/;if(bootverbose)printf("start_init:trying%.*s\n",(int)(next-path),path);/**Moveoutthebootflagargument.*/optio
ns=0;ucp=(char*)USRSTACK;(void)subyte(--ucp,0);/*trailingzero*/if(boothowto&RB_SINGLE){(void)subyte(--ucp,'s');options=1;}#ifdefnotyetif(boothowto&RB_FASTBOOT){(void)subyte(--ucp,'f');options=1;}#endif#ifdefBOOTCDROM(void)subyte(--ucp,'C');options=1;#endifif(options==0)(void)subyte(--ucp,'-');(void)subyte(--ucp,'-');/*leadinghyphen*/arg1=ucp;/**Moveoutthefilename(alsoarg0).*/(void)subyte(--ucp,0);for(s=next-1;s>=path;s--)(void)subyte(--ucp,*s);ar
g0=ucp;/**Moveouttheargpointers.*/uap=(char**)((intptr_t)ucp&~(sizeof(intptr_t)-1));(void)suword((caddr_t)--uap,(long)0);/*terminator*/(void)suword((caddr_t)--uap,(long)(intptr_t)arg1);(void)suword((caddr_t)--uap,(long)(intptr_t)arg0);/**Pointatthearguments.*/args.fname=arg0;args.argv=uap;args.envv=NULL;/**Nowtrytoexectheprogram.Ifcan'tforanyreason*otherthanitdoesn'texist,complain.**Otherwise,returnviafork_trampoline()alltheway*tousermodeasinit!*
/if((error=execve(p,&args))==0)return;if(error!=ENOENT)printf("exec%.*s:error%d\n",(int)(next-path),path,error);}printf("init:notfoundinpath%s\n",init_path);panic("noinit");}/**Likekthread_create(),butrunsinit'sownaddressspace.*Wedothisearlytoreservepid1.**Notespecialcase-donotmakeitrunnableyet.Otherwork*inprogresswillchangethismore.*/staticvoidcreate_init(constvoid*udata__unused){interror;ints;s=splhigh();error=fork1(&proc0,RFFDG|RFPROC,&initpro
c);if(error)panic("cannotforkinit:%d\n",error);initproc->p_flag|=P_INMEM|P_SYSTEM;cpu_set_fork_handler(initproc,start_init,NULL);remrunqueue(initproc);splx(s);}SYSINIT(init,SI_SUB_CREATE_INIT,SI_ORDER_FIRST,create_init,NULL)/**Makeitrunnablenow.*/staticvoidkick_init(constvoid*udata__unused){setrunqueue(initproc);}SYSINIT(kickinit,SI_SUB_KTHREAD_INIT,SI_ORDER_FIRST,kick_init,NULL)/**Systemcallswitchtable.**DONOTEDIT--thisfileisautomaticallygenerat
ed.*$FreeBSD:src/sys/kern/init_sysent.c,v1.79.2.102001/10/0507:38:43peterExp$*createdfromFreeBSD:src/sys/kern/syscalls.master,v1.72.2.82001/10/0507:34:36peterExp*/#include"opt_compat.h"#include<sys/param.h>#include<sys/sysent.h>#include<sys/sysproto.h>#defineAS(name)(sizeof(structname)/sizeof(register_t))#ifdefCOMPAT_43#definecompat(n,name)n,(sy_call_t*)__CONCAT(o,name)#else#definecompat(n,name)0,(sy_call_t*)nosys#endif/*Thecastsarebogusbutwilldo
fornow.*/structsysentsysent[]={{0,(sy_call_t*)nosys},/*0=syscall*/{AS(sys_exit_args),(sy_call_t*)sys_exit},/*1=exit*/{0,(sy_call_t*)fork},/*2=fork*/{AS(read_args),(sy_call_t*)read},/*3=read*/{AS(write_args),(sy_call_t*)write},/*4=write*/{AS(open_args),(sy_call_t*)open},/*5=open*/{AS(close_args),(sy_call_t*)close},/*6=close*/{AS(wait_args),(sy_call_t*)wait4},/*7=wait4*/{compat(AS(ocreat_args),creat)},/*8=oldcreat*/{AS(link_args),(sy_call_t*)link},
/*9=link*/{AS(unlink_args),(sy_call_t*)unlink},/*10=unlink*/{0,(sy_call_t*)nosys},/*11=obsoleteexecv*/{AS(chdir_args),(sy_call_t*)chdir},/*12=chdir*/{AS(fchdir_args),(sy_call_t*)fchdir},/*13=fchdir*/{AS(mknod_args),(sy_call_t*)mknod},/*14=mknod*/{AS(chmod_args),(sy_call_t*)chmod},/*15=chmod*/{AS(chown_args),(sy_call_t*)chown},/*16=chown*/{AS(obreak_args),(sy_call_t*)obreak},/*17=break*/{AS(getfsstat_args),(sy_call_t*)getfsstat},/*18=getfsstat*/{c
ompat(AS(olseek_args),lseek)},/*19=oldlseek*/{0,(sy_call_t*)getpid},/*20=getpid*/{AS(mount_args),(sy_call_t*)mount},/*21=mount*/{AS(unmount_args),(sy_call_t*)unmount},/*22=unmount*/{AS(setuid_args),(sy_call_t*)setuid},/*23=setuid*/{SYF_MPSAFE|0,(sy_call_t*)getuid},/*24=getuid*/{SYF_MPSAFE|0,(sy_call_t*)geteuid},/*25=geteuid*/{AS(ptrace_args),(sy_call_t*)ptrace},/*26=ptrace*/{AS(recvmsg_args),(sy_call_t*)recvmsg},/*27=recvmsg*/{AS(sendmsg_args),(s
y_call_t*)sendmsg},/*28=sendmsg*/{AS(recvfrom_args),(sy_call_t*)recvfrom},/*29=recvfrom*/{AS(accept_args),(sy_call_t*)accept},/*30=accept*/{AS(getpeername_args),(sy_call_t*)getpeername},/*31=getpeername*/{AS(getsockname_args),(sy_call_t*)getsockname},/*32=getsockname*/{AS(access_args),(sy_call_t*)access},/*33=access*/{AS(chflags_args),(sy_call_t*)chflags},/*34=chflags*/{AS(fchflags_args),(sy_call_t*)fchflags},/*35=fchflags*/{0,(sy_call_t*)sync},/
*36=sync*/{AS(kill_args),(sy_call_t*)kill},/*37=kill*/{compat(AS(ostat_args),stat)},/*38=oldstat*/{0,(sy_call_t*)getppid},/*39=getppid*/{compat(AS(olstat_args),lstat)},/*40=oldlstat*/{AS(dup_args),(sy_call_t*)dup},/*41=dup*/{0,(sy_call_t*)pipe},/*42=pipe*/{0,(sy_call_t*)getegid},/*43=getegid*/{AS(profil_args),(sy_call_t*)profil},/*44=profil*/{AS(ktrace_args),(sy_call_t*)ktrace},/*45=ktrace*/{compat(AS(osigaction_args),sigaction)},/*46=oldsigactio
n*/{SYF_MPSAFE|0,(sy_call_t*)getgid},/*47=getgid*/{compat(SYF_MPSAFE|AS(osigprocmask_args),sigprocmask)},/*48=oldsigprocmask*/{AS(getlogin_args),(sy_call_t*)getlogin},/*49=getlogin*/{AS(setlogin_args),(sy_call_t*)setlogin},/*50=setlogin*/{AS(acct_args),(sy_call_t*)acct},/*51=acct*/{compat(0,sigpending)},/*52=oldsigpending*/{AS(sigaltstack_args),(sy_call_t*)sigaltstack},/*53=sigaltstack*/{AS(ioctl_args),(sy_call_t*)ioctl},/*54=ioctl*/{AS(reboot_ar
gs),(sy_call_t*)reboot},/*55=reboot*/{AS(revoke_args),(sy_call_t*)revoke},/*56=revoke*/{AS(symlink_args),(sy_call_t*)symlink},/*57=symlink*/{AS(readlink_args),(sy_call_t*)readlink},/*58=readlink*/{AS(execve_args),(sy_call_t*)execve},/*59=execve*/{SYF_MPSAFE|AS(umask_args),(sy_call_t*)umask},/*60=umask*/{AS(chroot_args),(sy_call_t*)chroot},/*61=chroot*/{compat(AS(ofstat_args),fstat)},/*62=oldfstat*/{compat(AS(getkerninfo_args),getkerninfo)},/*63=o
ldgetkerninfo*/{compat(0,getpagesize)},/*64=oldgetpagesize*/{AS(msync_args),(sy_call_t*)msync},/*65=msync*/{0,(sy_call_t*)vfork},/*66=vfork*/{0,(sy_call_t*)nosys},/*67=obsoletevread*/{0,(sy_call_t*)nosys},/*68=obsoletevwrite*/{AS(sbrk_args),(sy_call_t*)sbrk},/*69=sbrk*/{AS(sstk_args),(sy_call_t*)sstk},/*70=sstk*/{compat(AS(ommap_args),mmap)},/*71=oldmmap*/{AS(ovadvise_args),(sy_call_t*)ovadvise},/*72=vadvise*/{AS(munmap_args),(sy_call_t*)munmap},
/*73=munmap*/{AS(mprotect_args),(sy_call_t*)mprotect},/*74=mprotect*/{AS(madvise_args),(sy_call_t*)madvise},/*75=madvise*/{0,(sy_call_t*)nosys},/*76=obsoletevhangup*/{0,(sy_call_t*)nosys},/*77=obsoletevlimit*/{AS(mincore_args),(sy_call_t*)mincore},/*78=mincore*/{AS(getgroups_args),(sy_call_t*)getgroups},/*79=getgroups*/{AS(setgroups_args),(sy_call_t*)setgroups},/*80=setgroups*/{SYF_MPSAFE|0,(sy_call_t*)getpgrp},/*81=getpgrp*/{AS(setpgid_args),(sy
_call_t*)setpgid},/*82=setpgid*/{AS(setitimer_args),(sy_call_t*)setitimer},/*83=setitimer*/{compat(0,wait)},/*84=oldwait*/{AS(swapon_args),(sy_call_t*)swapon},/*85=swapon*/{AS(getitimer_args),(sy_call_t*)getitimer},/*86=getitimer*/{compat(AS(gethostname_args),gethostname)},/*87=oldgethostname*/{compat(AS(sethostname_args),sethostname)},/*88=oldsethostname*/{0,(sy_call_t*)getdtablesize},/*89=getdtablesize*/{AS(dup2_args),(sy_call_t*)dup2},/*90=dup
2*/{0,(sy_call_t*)nosys},/*91=getdopt*/{AS(fcntl_args),(sy_call_t*)fcntl},/*92=fcntl*/{AS(select_args),(sy_call_t*)select},/*93=select*/{0,(sy_call_t*)nosys},/*94=setdopt*/{AS(fsync_args),(sy_call_t*)fsync},/*95=fsync*/{AS(setpriority_args),(sy_call_t*)setpriority},/*96=setpriority*/{AS(socket_args),(sy_call_t*)socket},/*97=socket*/{AS(connect_args),(sy_call_t*)connect},/*98=connect*/{compat(AS(accept_args),accept)},/*99=oldaccept*/{AS(getpriorit
y_args),(sy_call_t*)getpriority},/*100=getpriority*/{compat(AS(osend_args),send)},/*101=oldsend*/{compat(AS(orecv_args),recv)},/*102=oldrecv*/{compat(AS(osigreturn_args),sigreturn)},/*103=oldsigreturn*/{AS(bind_args),(sy_call_t*)bind},/*104=bind*/{AS(setsockopt_args),(sy_call_t*)setsockopt},/*105=setsockopt*/{AS(listen_args),(sy_call_t*)listen},/*106=listen*/{0,(sy_call_t*)nosys},/*107=obsoletevtimes*/{compat(AS(osigvec_args),sigvec)},/*108=oldsi
gvec*/{compat(AS(osigblock_args),sigblock)},/*109=oldsigblock*/{compat(AS(osigsetmask_args),sigsetmask)},/*110=oldsigsetmask*/{compat(AS(osigsuspend_args),sigsuspend)},/*111=oldsigsuspend*/{compat(AS(osigstack_args),sigstack)},/*112=oldsigstack*/{compat(AS(orecvmsg_args),recvmsg)},/*113=oldrecvmsg*/{compat(AS(osendmsg_args),sendmsg)},/*114=oldsendmsg*/{0,(sy_call_t*)nosys},/*115=obsoletevtrace*/{SYF_MPSAFE|AS(gettimeofday_args),(sy_call_t*)gettim
eofday},/*116=gettimeofday*/{AS(getrusage_args),(sy_call_t*)getrusage},/*117=getrusage*/{AS(getsockopt_args),(sy_call_t*)getsockopt},/*118=getsockopt*/{0,(sy_call_t*)nosys},/*119=resuba*/{AS(readv_args),(sy_call_t*)readv},/*120=readv*/{AS(writev_args),(sy_call_t*)writev},/*121=writev*/{AS(settimeofday_args),(sy_call_t*)settimeofday},/*122=settimeofday*/{AS(fchown_args),(sy_call_t*)fchown},/*123=fchown*/{AS(fchmod_args),(sy_call_t*)fchmod},/*124=f
chmod*/{compat(AS(recvfrom_args),recvfrom)},/*125=oldrecvfrom*/{AS(setreuid_args),(sy_call_t*)setreuid},/*126=setreuid*/{AS(setregid_args),(sy_call_t*)setregid},/*127=setregid*/{AS(rename_args),(sy_call_t*)rename},/*128=rename*/{compat(AS(otruncate_args),truncate)},/*129=oldtruncate*/{compat(AS(oftruncate_args),ftruncate)},/*130=oldftruncate*/{AS(flock_args),(sy_call_t*)flock},/*131=flock*/{AS(mkfifo_args),(sy_call_t*)mkfifo},/*132=mkfifo*/{AS(se

Hosted by uCoz