/**linux/fs/proc/array.c**Copyright(C)1992byLinusTorvalds*basedonideasbyDarrenSenn**Fixes:*Michael.K.Johnson:stat,statmextensions.*<johnsonm@stolaf.edu>**PaulineMiddelink:Madecmdline,envlineonlybreakat'\0's,to*makesureSET_PROCTITLEworks.Alsoremoved*b
ad'!'whichforcedaddressrecalculationfor*EVERYcharacteronthecurrentpage.*<middelin@polyware.iaf.nl>**DannyterHaar:addedcpuinfo*<dth@cistron.nl>**AlessandroRubini:profileextension.*<rubini@ipvvis.unipv.it>**JeffTranter:addedBogoMipsfieldtocpuinfo*<Jeff
_Tranter@Mitel.COM>**BrunoHaible:remove4Klimitforthemapsfile*<haible@ma2s2.mathematik.uni-karlsruhe.de>**YvesArrouye:removeremovaloftrailingspacesinget_array.*<Yves.Arrouye@marin.fdn.fr>**JeromeForissier:addedper-CPUtimeinformationto/proc/stat*and/pr
oc/<pid>/cpuextension*<forissier@isia.cma.fr>*-Incorporationandnon-SMPsafeoperation*offorissierpatchin2.1.78by*HansMarcus<crowbar@concepts.nl>**aeb@cwi.nl:/proc/partitions***AlanCox:securityfixes.*<Alan.Cox@linux.org>**GerhardWichert:addedBIGMEMsuppo
rt*SiemensAG<Gerhard.Wichert@pdb.siemens.de>*/#include<linux/types.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/kernel.h>#include<linux/kernel_stat.h>#include<linux/tty.h>#include<linux/user.h>#include<linux/a.out.h>#include<linux/s
tring.h>#include<linux/mman.h>#include<linux/proc_fs.h>#include<linux/ioport.h>#include<linux/config.h>#include<linux/mm.h>#include<linux/pagemap.h>#include<linux/swap.h>#include<linux/slab.h>#include<linux/smp.h>#include<linux/signal.h>#include<asm/
uaccess.h>#include<asm/pgtable.h>#include<asm/io.h>#defineLOAD_INT(x)((x)>>FSHIFT)#defineLOAD_FRAC(x)LOAD_INT(((x)&(FIXED_1-1))*100)#ifdefCONFIG_DEBUG_MALLOCintget_malloc(char*buffer);#endifstaticintopen_kcore(structinode*inode,structfile*filp){retur
ncapable(CAP_SYS_RAWIO)?0:-EPERM;}staticssize_tread_core(structfile*file,char*buf,size_tcount,loff_t*ppos){unsignedlongp=*ppos,memsize;ssize_tread;ssize_tcount1;char*pnt;structuserdump;#ifdefined(__i386__)||defined(__mc68000__)#defineFIRST_MAPPEDPAGE
_SIZE/*wedon'thavepage0mappedonx86..*/#else#defineFIRST_MAPPED0#endifmemset(&dump,0,sizeof(structuser));dump.magic=CMAGIC;dump.u_dsize=max_mapnr;#ifdefined(__i386__)dump.start_code=PAGE_OFFSET;#endif#ifdef__alpha__dump.start_data=PAGE_OFFSET;#endifme
msize=(max_mapnr+1)<<PAGE_SHIFT;if(p>=memsize)return0;if(count>memsize-p)count=memsize-p;read=0;if(p<sizeof(structuser)&&count>0){count1=count;if(p+count1>sizeof(structuser))count1=sizeof(structuser)-p;pnt=(char*)&dump+p;copy_to_user(buf,(void*)pnt,c
ount1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0&&p<PAGE_SIZE+FIRST_MAPPED){count1=PAGE_SIZE+FIRST_MAPPED-p;if(count1>count)count1=count;clear_user(buf,count1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0){copy_to_u
ser(buf,(void*)(PAGE_OFFSET+p-PAGE_SIZE),count);read+=count;}*ppos+=read;returnread;}staticstructfile_operationsproc_kcore_operations={NULL,/*lseek*/read_core,NULL,/*write*/NULL,/*readdir*/NULL,/*poll*/NULL,/*ioctl*/NULL,/*mmap*/open_kcore};structino
de_operationsproc_kcore_inode_operations={&proc_kcore_operations,};/**Thisfunctionaccessesprofilinginformation.Thereturneddatais*binary:thesamplingstepandtheactualcontentsoftheprofile*buffer.Useoftheprogramreadprofileisrecommendedinorderto*getmeaning
fulinfooutofthesedata.*/staticssize_tread_profile(structfile*file,char*buf,size_tcount,loff_t*ppos){unsignedlongp=*ppos;ssize_tread;char*pnt;unsignedintsample_step=1<<prof_shift;if(p>=(prof_len+1)*sizeof(unsignedint))return0;if(count>(prof_len+1)*siz
eof(unsignedint)-p)count=(prof_len+1)*sizeof(unsignedint)-p;read=0;while(p<sizeof(unsignedint)&&count>0){put_user(*((char*)(&sample_step)+p),buf);buf++;p++;count--;read++;}pnt=(char*)prof_buffer+p-sizeof(unsignedint);copy_to_user(buf,(void*)pnt,count
);read+=count;*ppos+=read;returnread;}/**Writingto/proc/profileresetsthecounters**Writinga'profilingmultiplier'valueintoitalsore-setstheprofiling*interruptfrequency,onarchitecturesthatsupportthis.*/staticssize_twrite_profile(structfile*file,constchar
*buf,size_tcount,loff_t*ppos){#ifdef__SMP__externintsetup_profiling_timer(unsignedintmultiplier);if(count==sizeof(int)){unsignedintmultiplier;if(copy_from_user(&multiplier,buf,sizeof(int)))return-EFAULT;if(setup_profiling_timer(multiplier))return-EIN
VAL;}#endifmemset(prof_buffer,0,prof_len*sizeof(*prof_buffer));returncount;}staticstructfile_operationsproc_profile_operations={NULL,/*lseek*/read_profile,write_profile,};structinode_operationsproc_profile_inode_operations={&proc_profile_operations,}
;staticintget_loadavg(char*buffer){inta,b,c;a=avenrun[0]+(FIXED_1/200);b=avenrun[1]+(FIXED_1/200);c=avenrun[2]+(FIXED_1/200);returnsprintf(buffer,"%d.%02d%d.%02d%d.%02d%d/%d%d\n",LOAD_INT(a),LOAD_FRAC(a),LOAD_INT(b),LOAD_FRAC(b),LOAD_INT(c),LOAD_FRAC
(c),nr_running,nr_tasks,last_pid);}staticintget_kstat(char*buffer){inti,len;unsignedsum=0;externunsignedlongtotal_forks;unsignedlongticks;ticks=jiffies*smp_num_cpus;#ifndefCONFIG_ARCH_S390for(i=0;i<NR_IRQS;i++)sum+=kstat_irqs(i);#endif#ifdef__SMP__le
n=sprintf(buffer,"cpu%u%u%u%lu\n",kstat.cpu_user,kstat.cpu_nice,kstat.cpu_system,jiffies*smp_num_cpus-(kstat.cpu_user+kstat.cpu_nice+kstat.cpu_system));for(i=0;i<smp_num_cpus;i++)len+=sprintf(buffer+len,"cpu%d%u%u%u%lu\n",i,kstat.per_cpu_user[cpu_log
ical_map(i)],kstat.per_cpu_nice[cpu_logical_map(i)],kstat.per_cpu_system[cpu_logical_map(i)],jiffies-(kstat.per_cpu_user[cpu_logical_map(i)]\+kstat.per_cpu_nice[cpu_logical_map(i)]\+kstat.per_cpu_system[cpu_logical_map(i)]));len+=sprintf(buffer+len,"
disk%u%u%u%u\n""disk_rio%u%u%u%u\n""disk_wio%u%u%u%u\n""disk_rblk%u%u%u%u\n""disk_wblk%u%u%u%u\n""page%u%u\n"#ifdefCONFIG_ARCH_S390"swap%u%u\n""intr10",#else"swap%u%u\n""intr%u",#endif#elselen=sprintf(buffer,"cpu%u%u%u%lu\n""disk%u%u%u%u\n""disk_rio%
u%u%u%u\n""disk_wio%u%u%u%u\n""disk_rblk%u%u%u%u\n""disk_wblk%u%u%u%u\n""page%u%u\n"#ifdefCONFIG_ARCH_S390"swap%u%u\n""intr10",#else"swap%u%u\n""intr%u",#endifkstat.cpu_user,kstat.cpu_nice,kstat.cpu_system,ticks-(kstat.cpu_user+kstat.cpu_nice+kstat.c
pu_system),#endifkstat.dk_drive[0],kstat.dk_drive[1],kstat.dk_drive[2],kstat.dk_drive[3],kstat.dk_drive_rio[0],kstat.dk_drive_rio[1],kstat.dk_drive_rio[2],kstat.dk_drive_rio[3],kstat.dk_drive_wio[0],kstat.dk_drive_wio[1],kstat.dk_drive_wio[2],kstat.d
k_drive_wio[3],kstat.dk_drive_rblk[0],kstat.dk_drive_rblk[1],kstat.dk_drive_rblk[2],kstat.dk_drive_rblk[3],kstat.dk_drive_wblk[0],kstat.dk_drive_wblk[1],kstat.dk_drive_wblk[2],kstat.dk_drive_wblk[3],kstat.pgpgin,kstat.pgpgout,kstat.pswpin,#ifdefCONFI
G_ARCH_S390kstat.pswpout);#elsekstat.pswpout,sum);for(i=0;i<NR_IRQS;i++)len+=sprintf(buffer+len,"%u",kstat_irqs(i));#endiflen+=sprintf(buffer+len,"\nctxt%u\n""btime%lu\n""processes%lu\n",kstat.context_swtch,xtime.tv_sec-jiffies/HZ,total_forks);return
len;}staticintget_uptime(char*buffer){unsignedlonguptime;unsignedlongidle;uptime=jiffies;idle=task[0]->times.tms_utime+task[0]->times.tms_stime;/*Theformulaforthefractionpartsreallyis((t*100)/HZ)%100,butthatwouldoverflowabouteveryfivedaysatHZ==100.Th
ereforetheidentitya=(a/b)*b+a%bisusedsothatitiscalculatedas(((t/HZ)*100)+((t%HZ)*100)/HZ)%100.Thepartinfrontofthe'+'alwaysevaluatesas0(mod100).Alldivisionsintheaboveformulasaretruncating.ForHZbeingapowerof10,thecalculationssimplifytotheversioninthe#e
lsepart(iftheprintfformatisadaptedtothesamenumberofdigitsaszeroesinHZ.*/#ifHZ!=100returnsprintf(buffer,"%lu.%02lu%lu.%02lu\n",uptime/HZ,(((uptime%HZ)*100)/HZ)%100,idle/HZ,(((idle%HZ)*100)/HZ)%100);#elsereturnsprintf(buffer,"%lu.%02lu%lu.%02lu\n",upti
me/HZ,uptime%HZ,idle/HZ,idle%HZ);#endif}staticintget_meminfo(char*buffer){structsysinfoi;intlen;si_meminfo(&i);si_swapinfo(&i);len=sprintf(buffer,"total:used:free:shared:buffers:cached:\n""Mem:%8lu%8lu%8lu%8lu%8lu%8lu\n""Swap:%8lu%8lu%8lu\n",i.totalr
am,i.totalram-i.freeram,i.freeram,i.sharedram,i.bufferram,page_cache_size*PAGE_SIZE,i.totalswap,i.totalswap-i.freeswap,i.freeswap);/**Taggedformat,foreasygreppingandexpansion.Theabovewillgoaway*eventually,oncethetoolshavebeenupdated.*/returnlen+sprin
tf(buffer+len,"MemTotal:%8lukB\n""MemFree:%8lukB\n""MemShared:%8lukB\n""Buffers:%8lukB\n""Cached:%8lukB\n""BigTotal:%8lukB\n""BigFree:%8lukB\n""SwapTotal:%8lukB\n""SwapFree:%8lukB\n",i.totalram>>10,i.freeram>>10,i.sharedram>>10,i.bufferram>>10,page_c
ache_size<<(PAGE_SHIFT-10),i.totalbig>>10,i.freebig>>10,i.totalswap>>10,i.freeswap>>10);}staticintget_version(char*buffer){externchar*linux_banner;strcpy(buffer,linux_banner);returnstrlen(buffer);}staticintget_cmdline(char*buffer){externcharsaved_com
mand_line[];returnsprintf(buffer,"%s\n",saved_command_line);}staticunsignedlongget_phys_addr(structtask_struct*p,unsignedlongptr){pgd_t*page_dir;pmd_t*page_middle;pte_tpte;if(!p||!p->mm||ptr>=TASK_SIZE)return0;/*CheckforNULLpgd..shouldn'thappen!*/if(
!p->mm->pgd){printk("get_phys_addr:pid%dhasNULLpgd!\n",p->pid);return0;}page_dir=pgd_offset(p->mm,ptr);if(pgd_none(*page_dir))return0;if(pgd_bad(*page_dir)){printk("badpagedirectoryentry%08lx\n",pgd_val(*page_dir));pgd_clear(page_dir);return0;}page_m
iddle=pmd_offset(page_dir,ptr);if(pmd_none(*page_middle))return0;if(pmd_bad(*page_middle)){printk("badpagemiddleentry%08lx\n",pmd_val(*page_middle));pmd_clear(page_middle);return0;}pte=*pte_offset(page_middle,ptr);if(!pte_present(pte))return0;returnp
te_page(pte)+(ptr&~PAGE_MASK);}#include<linux/bigmem.h>staticintget_array(structtask_struct*p,unsignedlongstart,unsignedlongend,char*buffer){unsignedlongaddr;intsize=0,result=0;charc;if(start>=end)returnresult;for(;;){addr=get_phys_addr(p,start);if(!
addr)returnresult;addr=kmap(addr,KM_READ);do{c=*(char*)addr;if(!c)result=size;if(size<PAGE_SIZE)buffer[size++]=c;else{kunmap(addr,KM_READ);returnresult;}addr++;start++;if(!c&&start>=end){kunmap(addr,KM_READ);returnresult;}}while(addr&~PAGE_MASK);kunm
ap(addr-1,KM_READ);}returnresult;}staticintget_env(intpid,char*buffer){structtask_struct*p;read_lock(&tasklist_lock);p=find_task_by_pid(pid);read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p||!p->mm)return0;returnget_array(p
,p->mm->env_start,p->mm->env_end,buffer);}staticintget_arg(intpid,char*buffer){structtask_struct*p;read_lock(&tasklist_lock);p=find_task_by_pid(pid);read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p||!p->mm)return0;returnget
_array(p,p->mm->arg_start,p->mm->arg_end,buffer);}/**Thesebracketthesleepingfunctions..*/externvoidscheduling_functions_start_here(void);externvoidscheduling_functions_end_here(void);#definefirst_sched((unsignedlong)scheduling_functions_start_here)#d
efinelast_sched((unsignedlong)scheduling_functions_end_here)staticunsignedlongget_wchan(structtask_struct*p){if(!p||p==current||p->state==TASK_RUNNING)return0;#ifdefined(__i386__){unsignedlongebp,esp,eip;unsignedlongstack_page;intcount=0;stack_page=(
unsignedlong)p;esp=p->tss.esp;if(!stack_page||esp<stack_page||esp>=8188+stack_page)return0;/*include/asm-i386/system.h:switch_to()pushesebplast.*/ebp=*(unsignedlong*)esp;do{if(ebp<stack_page||ebp>=8188+stack_page)return0;eip=*(unsignedlong*)(ebp+4);i
f(eip<first_sched||eip>=last_sched)returneip;ebp=*(unsignedlong*)ebp;}while(count++<16);}#elifdefined(__alpha__)/**Thisonedependsontheframesizeofschedule().Doa*"disassschedule"ingdbtofindtheframesize.Also,the*codeassumesthatsleep_on()followsimmediate
lyafter*interruptible_sleep_on()andthatadd_timer()follows*immediatelyafterinterruptible_sleep().Ugly,isn'tit?*Maybeaddingawchanfieldtotask_structwouldbebetter,*afterall...*/{unsignedlongschedule_frame;unsignedlongpc;pc=thread_saved_pc(&p->tss);if(pc>
=first_sched&&pc<last_sched){schedule_frame=((unsignedlong*)p->tss.ksp)[6];return((unsignedlong*)schedule_frame)[12];}returnpc;}#elifdefined(__mips__)/**ThesamecommentasontheAlphaapplieshere,too...*/{unsignedlongschedule_frame;unsignedlongpc;pc=threa
d_saved_pc(&p->tss);if(pc>=(unsignedlong)interruptible_sleep_on&&pc<(unsignedlong)add_timer){schedule_frame=((unsignedlong*)(long)p->tss.reg30)[16];return(unsignedlong)((unsignedlong*)schedule_frame)[11];}returnpc;}#elifdefined(__mc68000__){unsignedl
ongfp,pc;unsignedlongstack_page;intcount=0;stack_page=(unsignedlong)p;fp=((structswitch_stack*)p->tss.ksp)->a6;do{if(fp<stack_page+sizeof(structtask_struct)||fp>=8184+stack_page)return0;pc=((unsignedlong*)fp)[1];/*FIXME:Thisdependsontheorderofthesefu
nctions.*/if(pc<first_sched||pc>=last_sched)returnpc;fp=*(unsignedlong*)fp;}while(count++<16);}#elifdefined(__powerpc__){unsignedlongip,sp;unsignedlongstack_page=(unsignedlong)p;intcount=0;sp=p->tss.ksp;do{sp=*(unsignedlong*)sp;if(sp<stack_page||sp>=
stack_page+8188)return0;if(count>0){ip=*(unsignedlong*)(sp+4);if(ip<first_sched||ip>=last_sched)returnip;}}while(count++<16);}#elifdefined(__arm__){unsignedlongfp,lr;unsignedlongstack_page;intcount=0;stack_page=4096+(unsignedlong)p;fp=get_css_fp(&p->
tss);do{if(fp<stack_page||fp>4092+stack_page)return0;lr=pc_pointer(((unsignedlong*)fp)[-1]);if(lr<first_sched||lr>last_sched)returnlr;fp=*(unsignedlong*)(fp-12);}while(count++<16);}#elifdefined(__sparc__){unsignedlongpc,fp,bias=0;unsignedlongtask_bas
e=(unsignedlong)p;structreg_window*rw;intcount=0;#ifdef__sparc_v9__bias=STACK_BIAS;#endiffp=p->tss.ksp+bias;do{/*Bogusframepointer?*/if(fp<(task_base+sizeof(structtask_struct))||fp>=(task_base+(2*PAGE_SIZE)))break;rw=(structreg_window*)fp;pc=rw->ins[
7];if(pc<first_sched||pc>=last_sched)returnpc;fp=rw->ins[6]+bias;}while(++count<16);}#elifdefined(__s390__){unsignedlongksp,backchain,ip;unsignedlongstack_page;intcount=0;stack_page=(unsignedlong)p;ksp=p->tss.ksp;if(!stack_page||ksp<stack_page||ksp>=
8188+stack_page)return0;backchain=(*(unsignedlong*)ksp)&0x7fffffff;do{if(backchain<stack_page||backchain>=8188+stack_page)return0;ip=(*(unsignedlong*)(backchain+56))&0x7fffffff;if(ip<first_sched||ip>=last_sched)returnip;backchain=(*(unsignedlong*)bac
kchain)&0x7fffffff;}while(count++<16);}#endifreturn0;}#ifdefined(__i386__)#defineKSTK_EIP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1019])#defineKSTK_ESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1022])#elifdefined(__alpha__)/**Seearch/
alpha/kernel/ptrace.cfordetails.*/#definePT_REG(reg)(PAGE_SIZE-sizeof(structpt_regs)\+(long)&((structpt_regs*)0)->reg)#defineKSTK_EIP(tsk)\(*(unsignedlong*)(PT_REG(pc)+PAGE_SIZE+(unsignedlong)(tsk)))#defineKSTK_ESP(tsk)((tsk)==current?rdusp():(tsk)->
tss.usp)#elifdefined(__arm__)#defineKSTK_EIP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1022])#defineKSTK_ESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1020])#elifdefined(__mc68000__)#defineKSTK_EIP(tsk)\({\unsignedlongeip=0;\if((tsk)->t
ss.esp0>PAGE_SIZE&&\MAP_NR((tsk)->tss.esp0)<max_mapnr)\eip=((structpt_regs*)(tsk)->tss.esp0)->pc;\eip;})#defineKSTK_ESP(tsk)((tsk)==current?rdusp():(tsk)->tss.usp)#elifdefined(__powerpc__)#defineKSTK_EIP(tsk)((tsk)->tss.regs->nip)#defineKSTK_ESP(tsk)
((tsk)->tss.regs->gpr[1])#elifdefined(__sparc_v9__)#defineKSTK_EIP(tsk)((tsk)->tss.kregs->tpc)#defineKSTK_ESP(tsk)((tsk)->tss.kregs->u_regs[UREG_FP])#elifdefined(__sparc__)#defineKSTK_EIP(tsk)((tsk)->tss.kregs->pc)#defineKSTK_ESP(tsk)((tsk)->tss.kreg
s->u_regs[UREG_FP])#elifdefined(__mips__)#definePT_REG(reg)((long)&((structpt_regs*)0)->reg\-sizeof(structpt_regs))#defineKSTK_TOS(tsk)((unsignedlong)(tsk)+KERNEL_STACK_SIZE-32)#defineKSTK_EIP(tsk)(*(unsignedlong*)(KSTK_TOS(tsk)+PT_REG(cp0_epc)))#def
ineKSTK_ESP(tsk)(*(unsignedlong*)(KSTK_TOS(tsk)+PT_REG(regs[29])))#elifdefined(__s390__)#defineKSTK_EIP(tsk)((tsk)->tss.regs->psw.addr)#defineKSTK_ESP(tsk)((tsk)->tss.ksp)#endif/*Gccoptimizesaway"strlen(x)"forconstantx*/#defineADDBUF(buffer,string)\d
o{memcpy(buffer,string,strlen(string));\buffer+=strlen(string);}while(0)staticinlinechar*task_name(structtask_struct*p,char*buf){inti;char*name;ADDBUF(buf,"Name:\t");name=p->comm;i=sizeof(p->comm);do{unsignedcharc=*name;name++;i--;*buf=c;if(!c)break;
if(c=='\\'){buf[1]=c;buf+=2;continue;}if(c=='\n'){buf[0]='\\';buf[1]='n';buf+=2;continue;}buf++;}while(i);*buf='\n';returnbuf+1;}/**Thetaskstatearrayisastrange"bitmap"of*reasonstosleep.Thus"running"iszero,and*youcantestforcombinationsofotherswith*sim
plebittests.*/staticconstchar*task_state_array[]={"R(running)",/*0*/"S(sleeping)",/*1*/"D(disksleep)",/*2*/"Z(zombie)",/*4*/"T(stopped)",/*8*/"W(paging)"/*16*/};staticinlineconstchar*get_task_state(structtask_struct*tsk){unsignedintstate=tsk->state&(
TASK_RUNNING|TASK_INTERRUPTIBLE|TASK_UNINTERRUPTIBLE|TASK_ZOMBIE|TASK_STOPPED|TASK_SWAPPING);constchar**p=&task_state_array[0];while(state){p++;state>>=1;}return*p;}staticinlinechar*task_state(structtask_struct*p,char*buffer){intg;buffer+=sprintf(buf
fer,"State:\t%s\n""Pid:\t%d\n""PPid:\t%d\n""Uid:\t%d\t%d\t%d\t%d\n""Gid:\t%d\t%d\t%d\t%d\n""Groups:\t",get_task_state(p),p->pid,p->p_pptr->pid,p->uid,p->euid,p->suid,p->fsuid,p->gid,p->egid,p->sgid,p->fsgid);for(g=0;g<p->ngroups;g++)buffer+=sprintf(b
uffer,"%d",p->groups[g]);buffer+=sprintf(buffer,"\n");returnbuffer;}staticinlinechar*task_mem(structtask_struct*p,char*buffer){structmm_struct*mm=p->mm;if(mm&&mm!=&init_mm){structvm_area_struct*vma=mm->mmap;unsignedlongdata=0,stack=0;unsignedlongexec
=0,lib=0;for(vma=mm->mmap;vma;vma=vma->vm_next){unsignedlonglen=(vma->vm_end-vma->vm_start)>>10;if(!vma->vm_file){data+=len;if(vma->vm_flags&VM_GROWSDOWN)stack+=len;continue;}if(vma->vm_flags&VM_WRITE)continue;if(vma->vm_flags&VM_EXEC){exec+=len;if(v
ma->vm_flags&VM_EXECUTABLE)continue;lib+=len;}}buffer+=sprintf(buffer,"VmSize:\t%8lukB\n""VmLck:\t%8lukB\n""VmRSS:\t%8lukB\n""VmData:\t%8lukB\n""VmStk:\t%8lukB\n""VmExe:\t%8lukB\n""VmLib:\t%8lukB\n",mm->total_vm<<(PAGE_SHIFT-10),mm->locked_vm<<(PAGE_
SHIFT-10),mm->rss<<(PAGE_SHIFT-10),data-stack,stack,exec-lib,lib);}returnbuffer;}staticvoidcollect_sigign_sigcatch(structtask_struct*p,sigset_t*ign,sigset_t*catch){structk_sigaction*k;inti;sigemptyset(ign);sigemptyset(catch);if(p->sig){k=p->sig->acti
on;for(i=1;i<=_NSIG;++i,++k){if(k->sa.sa_handler==SIG_IGN)sigaddset(ign,i);elseif(k->sa.sa_handler!=SIG_DFL)sigaddset(catch,i);}}}staticinlinechar*task_sig(structtask_struct*p,char*buffer){sigset_tign,catch;buffer+=sprintf(buffer,"SigPnd:\t");buffer=
render_sigset_t(&p->signal,buffer);*buffer++='\n';buffer+=sprintf(buffer,"SigBlk:\t");buffer=render_sigset_t(&p->blocked,buffer);*buffer++='\n';collect_sigign_sigcatch(p,&ign,&catch);buffer+=sprintf(buffer,"SigIgn:\t");buffer=render_sigset_t(&ign,buf
fer);*buffer++='\n';buffer+=sprintf(buffer,"SigCgt:\t");/*Linux2.0uses"SigCgt"*/buffer=render_sigset_t(&catch,buffer);*buffer++='\n';returnbuffer;}externinlinechar*task_cap(structtask_struct*p,char*buffer){returnbuffer+sprintf(buffer,"CapInh:\t%016x\
n""CapPrm:\t%016x\n""CapEff:\t%016x\n",cap_t(p->cap_inheritable),cap_t(p->cap_permitted),cap_t(p->cap_effective));}staticintget_status(intpid,char*buffer){char*orig=buffer;structtask_struct*tsk;read_lock(&tasklist_lock);tsk=find_task_by_pid(pid);read
_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!tsk)return0;buffer=task_name(tsk,buffer);buffer=task_state(tsk,buffer);buffer=task_mem(tsk,buffer);buffer=task_sig(tsk,buffer);buffer=task_cap(tsk,buffer);#if__s390__buffer=task_sh
ow_regs(tsk,buffer);#endifreturnbuffer-orig;}staticintget_stat(intpid,char*buffer){structtask_struct*tsk;unsignedlongvsize,eip,esp,wchan;longpriority,nice;inttty_pgrp;sigset_tsigign,sigcatch;charstate;read_lock(&tasklist_lock);tsk=find_task_by_pid(pi
d);if(!tsk){read_unlock(&tasklist_lock);return0;}state=*get_task_state(tsk);vsize=eip=esp=0;if(tsk->mm&&tsk->mm!=&init_mm){structvm_area_struct*vma=tsk->mm->mmap;while(vma){vsize+=vma->vm_end-vma->vm_start;vma=vma->vm_next;}if((current->fsuid==tsk->e
uid&&tsk->dumpable&&cap_issubset(tsk->cap_permitted,current->cap_permitted))||capable(CAP_DAC_OVERRIDE)){eip=KSTK_EIP(tsk);esp=KSTK_ESP(tsk);}}read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/wchan=get_wchan(tsk);collect_sigign_s
igcatch(tsk,&sigign,&sigcatch);if(tsk->tty)tty_pgrp=tsk->tty->pgrp;elsetty_pgrp=-1;/*scalepriorityandnicevaluesfromtimeslicesto-20..20*//*tomakeitlooklikea"normal"Unixpriority/nicevalue*/priority=tsk->counter;priority=20-(priority*10+DEF_PRIORITY/2)/
DEF_PRIORITY;nice=tsk->priority;nice=20-(nice*20+DEF_PRIORITY/2)/DEF_PRIORITY;returnsprintf(buffer,"%d(%s)%c%d%d%d%d%d%lu%lu\%lu%lu%lu%lu%lu%ld%ld%ld%ld%ld%ld%lu%lu%ld%lu%lu%lu%lu%lu\%lu%lu%lu%lu%lu%lu%lu%lu%d%d\n",pid,tsk->comm,state,tsk->p_pptr->pi
d,tsk->pgrp,tsk->session,tsk->tty?kdev_t_to_nr(tsk->tty->device):0,tty_pgrp,tsk->flags,tsk->min_flt,tsk->cmin_flt,tsk->maj_flt,tsk->cmaj_flt,tsk->times.tms_utime,tsk->times.tms_stime,tsk->times.tms_cutime,tsk->times.tms_cstime,priority,nice,0UL/*remo
ved*/,tsk->it_real_value,tsk->start_time,vsize,tsk->mm?tsk->mm->rss:0,/*youmightwanttoshiftthisleft3*/tsk->rlim?tsk->rlim[RLIMIT_RSS].rlim_cur:0,tsk->mm?tsk->mm->start_code:0,tsk->mm?tsk->mm->end_code:0,tsk->mm?tsk->mm->start_stack:0,esp,eip,/*Thesig
nalinformationhereisobsolete.*ItmustbedecimalforLinux2.0compatibility.*Use/proc/#/statusforreal-timesignals.*/tsk->signal.sig[0]&0x7fffffffUL,tsk->blocked.sig[0]&0x7fffffffUL,sigign.sig[0]&0x7fffffffUL,sigcatch.sig[0]&0x7fffffffUL,wchan,tsk->nswap,ts
k->cnswap,tsk->exit_signal,tsk->processor);}staticinlinevoidstatm_pte_range(pmd_t*pmd,unsignedlongaddress,unsignedlongsize,int*pages,int*shared,int*dirty,int*total){pte_t*pte;unsignedlongend;if(pmd_none(*pmd))return;if(pmd_bad(*pmd)){printk("statm_pt
e_range:badpmd(%08lx)\n",pmd_val(*pmd));pmd_clear(pmd);return;}pte=pte_offset(pmd,address);address&=~PMD_MASK;end=address+size;if(end>PMD_SIZE)end=PMD_SIZE;do{pte_tpage=*pte;address+=PAGE_SIZE;pte++;if(pte_none(page))continue;++*total;if(!pte_present
(page))continue;++*pages;if(pte_dirty(page))++*dirty;if(MAP_NR(pte_page(page))>=max_mapnr)continue;if(atomic_read(&mem_map[MAP_NR(pte_page(page))].count)>1)++*shared;}while(address<end);}staticinlinevoidstatm_pmd_range(pgd_t*pgd,unsignedlongaddress,u
nsignedlongsize,int*pages,int*shared,int*dirty,int*total){pmd_t*pmd;unsignedlongend;if(pgd_none(*pgd))return;if(pgd_bad(*pgd)){printk("statm_pmd_range:badpgd(%08lx)\n",pgd_val(*pgd));pgd_clear(pgd);return;}pmd=pmd_offset(pgd,address);address&=~PGDIR_
MASK;end=address+size;if(end>PGDIR_SIZE)end=PGDIR_SIZE;do{statm_pte_range(pmd,address,end-address,pages,shared,dirty,total);address=(address+PMD_SIZE)&PMD_MASK;pmd++;}while(address<end);}staticvoidstatm_pgd_range(pgd_t*pgd,unsignedlongaddress,unsigne
dlongend,int*pages,int*shared,int*dirty,int*total){while(address<end){statm_pmd_range(pgd,address,end-address,pages,shared,dirty,total);address=(address+PGDIR_SIZE)&PGDIR_MASK;pgd++;}}staticintget_statm(intpid,char*buffer){structtask_struct*tsk;intsi
ze=0,resident=0,share=0,trs=0,lrs=0,drs=0,dt=0;read_lock(&tasklist_lock);tsk=find_task_by_pid(pid);read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!tsk)return0;if(tsk->mm&&tsk->mm!=&init_mm){structvm_area_struct*vma=tsk->mm->
mmap;while(vma){pgd_t*pgd=pgd_offset(tsk->mm,vma->vm_start);intpages=0,shared=0,dirty=0,total=0;statm_pgd_range(pgd,vma->vm_start,vma->vm_end,&pages,&shared,&dirty,&total);resident+=pages;share+=shared;dt+=dirty;size+=total;if(vma->vm_flags&VM_EXECUT
ABLE)trs+=pages;/*text*/elseif(vma->vm_flags&VM_GROWSDOWN)drs+=pages;/*stack*/elseif(vma->vm_end>0x60000000)lrs+=pages;/*library*/elsedrs+=pages;vma=vma->vm_next;}}returnsprintf(buffer,"%d%d%d%d%d%d%d\n",size,resident,share,trs,lrs,drs,dt);}/**Theway
wesupportsyntheticfiles>4K*-withoutstoringtheircontentsinsomebufferand*-withoutwalkingthroughtheentiresyntheticfileuntilwereachthe*positionoftherequesteddata*istocleverlyencodethecurrentpositioninthefile'sf_posfield.*Thereisnorequirementthataread()ca
llwhichreturns`count'bytes*ofdataincreasesf_posbyexactly`count'.**ThisideaisLinus'one.Brunoimplementedit.*//**Forthe/proc/<pid>/mapsfile,weusefixedlengthrecords,eachcontaining*asingleline.*/#defineMAPS_LINE_LENGTH4096#defineMAPS_LINE_SHIFT12/**f_pos=
(numberofthevmainthetask->mm->mmaplist)*MAPS_LINE_LENGTH*+(indexintotheline)*//*forsystemswithsizeof(void*)==4:*/#defineMAPS_LINE_FORMAT4"%08lx-%08lx%s%08lx%s%lu"#defineMAPS_LINE_MAX449/*sumof8181418151101*//*forsystemswithsizeof(void*)==8:*/#defineM
APS_LINE_FORMAT8"%016lx-%016lx%s%016lx%s%lu"#defineMAPS_LINE_MAX873/*sumof1611614116151101*/#defineMAPS_LINE_MAXMAPS_LINE_MAX8staticssize_tread_maps(intpid,structfile*file,char*buf,size_tcount,loff_t*ppos){structtask_struct*p;structvm_area_struct*map
,*next;char*destptr=buf,*buffer;loff_tlineno;ssize_tcolumn,i;intvolatile_task;longretval;/**Wemightsleepgettingthepage,sogetitfirst.*/retval=-ENOMEM;buffer=(char*)__get_free_page(GFP_KERNEL);if(!buffer)gotoout;retval=-EINVAL;read_lock(&tasklist_lock)
;p=find_task_by_pid(pid);read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p)gotofreepage_out;if(!p->mm||p->mm==&init_mm||count==0)gotogetlen_out;/*Checkwhetherthemmapscouldchangeifwesleep*/volatile_task=(p!=current||atomic_re
ad(&p->mm->count)>1);/*decodef_pos*/lineno=*ppos>>MAPS_LINE_SHIFT;column=*ppos&(MAPS_LINE_LENGTH-1);/*quicklygotolinelineno*/for(map=p->mm->mmap,i=0;map&&(i<lineno);map=map->vm_next,i++)continue;for(;map;map=next){/*producethenextline*/char*line;char
str[5],*cp=str;intflags;kdev_tdev;unsignedlongino;intmaxlen=(sizeof(void*)==4)?MAPS_LINE_MAX4:MAPS_LINE_MAX8;intlen;/**Getthenextvmanow(butitwon'tbeusedifwesleep).*/next=map->vm_next;flags=map->vm_flags;*cp++=flags&VM_READ?'r':'-';*cp++=flags&VM_WRIT
E?'w':'-';*cp++=flags&VM_EXEC?'x':'-';*cp++=flags&VM_MAYSHARE?'s':'p';*cp++=0;dev=0;ino=0;if(map->vm_file!=NULL){dev=map->vm_file->f_dentry->d_inode->i_dev;ino=map->vm_file->f_dentry->d_inode->i_ino;line=d_path(map->vm_file->f_dentry,buffer,PAGE_SIZE
);buffer[PAGE_SIZE-1]='\n';line-=maxlen;if(line<buffer)line=buffer;}elseline=buffer;len=sprintf(line,sizeof(void*)==4?MAPS_LINE_FORMAT4:MAPS_LINE_FORMAT8,map->vm_start,map->vm_end,str,map->vm_offset,kdevname(dev),ino);if(map->vm_file){for(i=len;i<max
len;i++)line[i]='';len=buffer+PAGE_SIZE-line;}elseline[len++]='\n';if(column>=len){column=0;/*continuewithnextlineatcolumn0*/lineno++;continue;/*wehaven'tslept*/}i=len-column;if(i>count)i=count;copy_to_user(destptr,line+column,i);/*mayhaveslept*/dest
ptr+=i;count-=i;column+=i;if(column>=len){column=0;/*nexttime:nextlineatcolumn0*/lineno++;}/*done?*/if(count==0)break;/*Bywritingtouserspace,wemighthaveslept.*Stoptheloop,toavoidaracecondition.*/if(volatile_task)break;}/*encodef_pos*/*ppos=(lineno<<M
APS_LINE_SHIFT)+column;getlen_out:retval=destptr-buf;freepage_out:free_page((unsignedlong)buffer);out:returnretval;}#ifdef__SMP__staticintget_pidcpu(intpid,char*buffer){structtask_struct*tsk=current;inti,len;read_lock(&tasklist_lock);if(pid!=tsk->pid
)tsk=find_task_by_pid(pid);read_unlock(&tasklist_lock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(tsk==NULL)return0;len=sprintf(buffer,"cpu%lu%lu\n",tsk->times.tms_utime,tsk->times.tms_stime);for(i=0;i<smp_num_cpus;i++)len+=sprintf(buffer+len,"cpu%
d%lu%lu\n",i,tsk->per_cpu_utime[cpu_logical_map(i)],tsk->per_cpu_stime[cpu_logical_map(i)]);returnlen;}#endif#ifdefCONFIG_MODULESexternintget_module_list(char*);externintget_ksyms_list(char*,char**,off_t,int);#endifexternintget_device_list(char*);ext
ernintget_partition_list(char*,char**,off_t,int);externintget_filesystem_list(char*);externintget_filesystem_info(char*);#ifndefCONFIG_ARCH_S390externintget_irq_list(char*);#endifexternintget_dma_list(char*);externintget_cpuinfo(char*);externintget_p
ci_list(char*);externintget_md_status(char*);externintget_rtc_status(char*);externintget_locks_status(char*,char**,off_t,int);externintget_swaparea_info(char*);externintget_hardware_list(char*);externintget_stram_list(char*);staticlongget_root_array(
char*page,inttype,char**start,off_toffset,unsignedlonglength){switch(type){casePROC_LOADAVG:returnget_loadavg(page);casePROC_UPTIME:returnget_uptime(page);casePROC_MEMINFO:returnget_meminfo(page);#ifdefCONFIG_PCI_OLD_PROCcasePROC_PCI:returnget_pci_li
st(page);#endif#ifdefCONFIG_NUBUScasePROC_NUBUS:returnget_nubus_list(page);#endifcasePROC_CPUINFO:returnget_cpuinfo(page);casePROC_VERSION:returnget_version(page);#ifdefCONFIG_DEBUG_MALLOCcasePROC_MALLOC:returnget_malloc(page);#endif#ifdefCONFIG_MODU
LEScasePROC_MODULES:returnget_module_list(page);casePROC_KSYMS:returnget_ksyms_list(page,start,offset,length);#endifcasePROC_STAT:returnget_kstat(page);casePROC_SLABINFO:returnget_slabinfo(page);casePROC_DEVICES:returnget_device_list(page);casePROC_P
ARTITIONS:returnget_partition_list(page,start,offset,length);#ifndefCONFIG_ARCH_S390casePROC_INTERRUPTS:returnget_irq_list(page);#endifcasePROC_FILESYSTEMS:returnget_filesystem_list(page);#ifndefCONFIG_ARCH_S390casePROC_DMA:returnget_dma_list(page);#
endifcasePROC_IOPORTS:returnget_ioport_list(page);#ifdefCONFIG_BLK_DEV_MDcasePROC_MD:returnget_md_status(page);#endifcasePROC_CMDLINE:returnget_cmdline(page);casePROC_MTAB:returnget_filesystem_info(page);casePROC_SWAP:returnget_swaparea_info(page);#i
fdefCONFIG_RTCcasePROC_RTC:returnget_rtc_status(page);#endif#ifdefCONFIG_SGI_DS1286casePROC_RTC:returnget_ds1286_status(page);#endifcasePROC_LOCKS:returnget_locks_status(page,start,offset,length);#ifdefCONFIG_PROC_HARDWAREcasePROC_HARDWARE:returnget_
hardware_list(page);#endif#ifdefCONFIG_STRAM_PROCcasePROC_STRAM:returnget_stram_list(page);#endif}return-EBADF;}staticintprocess_unauthorized(inttype,intpid){structtask_struct*p;uid_teuid=0;/*Savetheeuidkeepthelockshort*/intok=0;read_lock(&tasklist_l
ock);/**Grabthelock,findthetask,savetheuidand*checkithasanmmstill(ieitsnotdead)*/p=find_task_by_pid(pid);if(p){euid=p->euid;ok=p->dumpable;if(!cap_issubset(p->cap_permitted,current->cap_permitted))ok=0;if(!p->mm)/*Scoobyscoobydoowhereareyou?*/p=NULL;
}read_unlock(&tasklist_lock);if(!p)return1;switch(type){casePROC_PID_STATUS:casePROC_PID_STATM:casePROC_PID_STAT:casePROC_PID_MAPS:casePROC_PID_CMDLINE:casePROC_PID_CPU:return0;}if((current->fsuid==euid&&ok)||capable(CAP_DAC_OVERRIDE))return0;return1
;}staticintget_process_array(char*page,intpid,inttype){switch(type){casePROC_PID_STATUS:returnget_status(pid,page);casePROC_PID_ENVIRON:returnget_env(pid,page);casePROC_PID_CMDLINE:returnget_arg(pid,page);casePROC_PID_STAT:returnget_stat(pid,page);ca
sePROC_PID_STATM:returnget_statm(pid,page);#ifdef__SMP__casePROC_PID_CPU:returnget_pidcpu(pid,page);#endif}return-EBADF;}staticinlineintfill_array(char*page,intpid,inttype,char**start,off_toffset,intlength){if(pid)returnget_process_array(page,pid,typ
e);returnget_root_array(page,type,start,offset,length);}#definePROC_BLOCK_SIZE(3*1024)/*4Kpagesizebutouroutputroutinesusesomeslackforoverruns*/staticssize_tarray_read(structfile*file,char*buf,size_tcount,loff_t*ppos){structinode*inode=file->f_dentry-
>d_inode;unsignedlongpage;char*start;ssize_tlength;ssize_tend;unsignedinttype,pid;structproc_dir_entry*dp;if(count>PROC_BLOCK_SIZE)count=PROC_BLOCK_SIZE;if(!(page=__get_free_page(GFP_KERNEL)))return-ENOMEM;type=inode->i_ino;pid=type>>16;type&=0x0000f
fff;start=NULL;dp=(structproc_dir_entry*)inode->u.generic_ip;if(pid&&process_unauthorized(type,pid)){free_page(page);return-EIO;}if(dp->get_info)length=dp->get_info((char*)page,&start,*ppos,count,0);elselength=fill_array((char*)page,pid,type,&start,*
ppos,count);if(length<0){free_page(page);returnlength;}if(start!=NULL){/*Wehavehadblock-adjustingprocessing!*/copy_to_user(buf,start,length);*ppos+=length;count=length;}else{/*Static4kB(orwhatever)blockcapacity*/if(*ppos>=length){free_page(page);retu
rn0;}if(count+*ppos>length)count=length-*ppos;end=count+*ppos;copy_to_user(buf,(char*)page+*ppos,count);*ppos=end;}free_page(page);returncount;}staticstructfile_operationsproc_array_operations={NULL,/*array_lseek*/array_read,NULL,/*array_write*/NULL,
/*array_readdir*/NULL,/*array_poll*/NULL,/*array_ioctl*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};structinode_operationsproc_array_inode_operations={&proc_array_operations,/*defaultbasedirec
toryfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NUL
L/*permission*/};staticssize_tarraylong_read(structfile*file,char*buf,size_tcount,loff_t*ppos){structinode*inode=file->f_dentry->d_inode;unsignedintpid=inode->i_ino>>16;unsignedinttype=inode->i_ino&0x0000ffff;switch(type){casePROC_PID_MAPS:returnread
_maps(pid,file,buf,count,ppos);}return-EINVAL;}staticstructfile_operationsproc_arraylong_operations={NULL,/*array_lseek*/arraylong_read,NULL,/*array_write*/NULL,/*array_readdir*/NULL,/*array_poll*/NULL,/*array_ioctl*/NULL,/*mmap*/NULL,/*nospecialopen
code*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};structinode_operationsproc_arraylong_inode_operations={&proc_arraylong_operations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*sy
mlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};/**linux/fs/proc/base.c**Copyright(C)1991,1992LinusTorvalds**pro
cbasedirectoryhandlingfunctions*/#include<asm/uaccess.h>#include<linux/config.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/proc_fs.h>#include<linux/stat.h>#include<linux/init.h>staticstructfile_operationsproc_base_operations={NULL,/
*lseek-default*/NULL,/*read-bad*/NULL,/*write-bad*/proc_readdir,/*readdir*/NULL,/*poll-default*/NULL,/*ioctl-default*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};/**procdirectoriescandoalmostn
othing..*/staticstructinode_operationsproc_base_inode_operations={&proc_base_operations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/proc_lookup,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*
rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};/**Thefillargumentisnon-zerowhentheinodeisbeingfilled...*wedon'tneedtodoanythingwhenit'sbeingdeleted.*/staticvoidproc_pi
d_fill_inode(structinode*inode,intfill){structtask_struct*p;intpid=inode->i_ino>>16;intino=inode->i_ino&0xffff;read_lock(&tasklist_lock);if(fill&&(p=find_task_by_pid(pid))!=NULL){uid_tuid=0;gid_tgid=0;if(p->dumpable||ino==PROC_PID_INO){uid=p->euid;gi
d=p->egid;}inode->i_uid=uid;inode->i_gid=gid;}read_unlock(&tasklist_lock);}/**Thisisreallyapseudo-entry,andonlylinks*backwardstotheparentwithnolinkfromthe*rootdirectorytothis.Thiswaywecanhavejust*oneentryforevery/proc/<pid>/directory.*/structproc_dir
_entryproc_pid={PROC_PID_INO,5,"<pid>",S_IFDIR|S_IRUGO|S_IXUGO,2,0,0,0,&proc_base_inode_operations,NULL,proc_pid_fill_inode,NULL,&proc_root,NULL};staticstructproc_dir_entryproc_pid_status={PROC_PID_STATUS,6,"status",S_IFREG|S_IRUGO,1,0,0,0,&proc_arra
y_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_mem={PROC_PID_MEM,3,"mem",S_IFREG|S_IRUSR|S_IWUSR,1,0,0,0,&proc_mem_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_cwd={PROC_PID_CWD,3,"c
wd",S_IFLNK|S_IRWXU,1,0,0,0,&proc_link_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_root={PROC_PID_ROOT,4,"root",S_IFLNK|S_IRWXU,1,0,0,0,&proc_link_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_ent
ryproc_pid_exe={PROC_PID_EXE,3,"exe",S_IFLNK|S_IRWXU,1,0,0,0,&proc_link_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_fd={PROC_PID_FD,2,"fd",S_IFDIR|S_IRUSR|S_IXUSR,2,0,0,0,&proc_fd_inode_operations,NULL,proc_pid_fill
_inode,};staticstructproc_dir_entryproc_pid_environ={PROC_PID_ENVIRON,7,"environ",S_IFREG|S_IRUSR,1,0,0,0,&proc_array_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_cmdline={PROC_PID_CMDLINE,7,"cmdline",S_IFREG|S_IRUGO
,1,0,0,0,&proc_array_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_stat={PROC_PID_STAT,4,"stat",S_IFREG|S_IRUGO,1,0,0,0,&proc_array_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_statm=
{PROC_PID_STATM,5,"statm",S_IFREG|S_IRUGO,1,0,0,0,&proc_array_inode_operations,NULL,proc_pid_fill_inode,};staticstructproc_dir_entryproc_pid_maps={PROC_PID_MAPS,4,"maps",S_IFIFO|S_IRUGO,1,0,0,0,&proc_arraylong_inode_operations,NULL,proc_pid_fill_inod
e,};#ifCONFIG_AP1000staticstructproc_dir_entryproc_pid_ringbuf={PROC_PID_RINGBUF,7,"ringbuf",S_IFREG|S_IRUGO|S_IWUSR,1,0,0,0,&proc_ringbuf_inode_operations,NULL,proc_pid_fill_inode,};#endif#ifdef__SMP__staticstructproc_dir_entryproc_pid_cpu={PROC_PID
_CPU,3,"cpu",S_IFREG|S_IRUGO,1,0,0,0,&proc_array_inode_operations,NULL,proc_pid_fill_inode,};#endif__initfunc(voidproc_base_init(void)){#ifCONFIG_AP1000proc_register(&proc_pid,&proc_pid_ringbuf);#endifproc_register(&proc_pid,&proc_pid_status);proc_re
gister(&proc_pid,&proc_pid_mem);proc_register(&proc_pid,&proc_pid_cwd);proc_register(&proc_pid,&proc_pid_root);proc_register(&proc_pid,&proc_pid_exe);proc_register(&proc_pid,&proc_pid_fd);proc_register(&proc_pid,&proc_pid_environ);proc_register(&proc
_pid,&proc_pid_cmdline);proc_register(&proc_pid,&proc_pid_stat);proc_register(&proc_pid,&proc_pid_statm);proc_register(&proc_pid,&proc_pid_maps);#ifdef__SMP__proc_register(&proc_pid,&proc_pid_cpu);#endif};/**linux/fs/proc/fd.c**Copyright(C)1991,1992L
inusTorvalds**procfddirectoryhandlingfunctions**01-May-98EdgarToernig<froese@gmx.de>*Addedsupportformorethan256fds.*Limitraisedto32768.*/#include<linux/errno.h>#include<linux/sched.h>#include<linux/file.h>#include<linux/proc_fs.h>#include<linux/stat.
h>#include<asm/uaccess.h>staticintproc_readfd(structfile*,void*,filldir_t);staticstructdentry*proc_lookupfd(structinode*,structdentry*);staticstructfile_operationsproc_fd_operations={NULL,/*lseek-default*/NULL,/*read-bad*/NULL,/*write-bad*/proc_readf
d,/*readdir*/NULL,/*poll-default*/NULL,/*ioctl-default*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};/**procdirectoriescandoalmostnothing..*/structinode_operationsproc_fd_inode_operations={&pro
c_fd_operations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/proc_lookupfd,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*w
ritepage*/NULL,/*bmap*/NULL,/*truncate*/proc_permission/*permission*/};/**NOTE!Normallywe'dindicatethatafiledoesnot*existbycreatinganegativedentryandreturning*asuccessfulreturncode.However,forthiscase*wedonotwanttocreatenegativedentries,because*thest
ateoftheworldcanchangebehindourbacks.**Thusjustreturn-ENOENTinstead.*/staticstructdentry*proc_lookupfd(structinode*dir,structdentry*dentry){unsignedintino,pid,fd,c;structtask_struct*p;structfile*file;structinode*inode;constchar*name;intlen,err;err=-E
NOENT;ino=dir->i_ino;pid=ino>>16;ino&=0x0000ffff;if(!pid||ino!=PROC_PID_FD)gotoout;fd=0;len=dentry->d_name.len;name=dentry->d_name.name;if(len>1&&*name=='0')gotoout;while(len-->0){c=*name-'0';name++;if(c>9)gotoout;fd*=10;fd+=c;if(fd&0xffff8000)gotoou
t;}read_lock(&tasklist_lock);file=NULL;p=find_task_by_pid(pid);if(p)file=fcheck_task(p,fd);read_unlock(&tasklist_lock);/**Filehandleisinvalidifitisoutofrange,iftheprocess*hasnofiles(Zombie)ifthefileisclosed,orifitsinode*isNULL*/if(!file||!file->f_den
try)gotoout;ino=(pid<<16)+PROC_PID_FD_DIR+fd;inode=proc_get_inode(dir->i_sb,ino,NULL);if(inode){dentry->d_op=&proc_dentry_operations;d_add(dentry,inode);returnNULL;}out:returnERR_PTR(err);}#defineNUMBUF10staticintproc_readfd(structfile*filp,void*dire
nt,filldir_tfilldir){structinode*inode=filp->f_dentry->d_inode;structtask_struct*p,**tarrayp;unsignedintfd,pid,ino;intretval;charbuf[NUMBUF];retval=0;ino=inode->i_ino;pid=ino>>16;ino&=0x0000ffff;if(ino!=PROC_PID_FD)gotoout;for(fd=filp->f_pos;fd<2;fd+
+,filp->f_pos++){ino=inode->i_ino;if(fd)ino=(ino&0xffff0000)|PROC_PID_INO;if(filldir(dirent,"..",fd+1,fd,ino)<0)gotoout;}read_lock(&tasklist_lock);p=find_task_by_pid(pid);if(!p)gotoout_unlock;tarrayp=p->tarray_ptr;for(fd-=2;p->files&&fd<p->files->max
_fds;fd++,filp->f_pos++){structfile*file=fcheck_task(p,fd);unsignedinti,j;if(!file||!file->f_dentry)continue;j=NUMBUF;i=fd;do{j--;buf[j]='0'+(i%10);i/=10;}while(i);/*Dropthetasklock,asthefilldirfunctionmayblock*/read_unlock(&tasklist_lock);ino=(pid<<
16)+PROC_PID_FD_DIR+fd;if(filldir(dirent,buf+j,NUMBUF-j,fd+2,ino)<0)gotoout;read_lock(&tasklist_lock);/*filldir()mighthaveslept,sowemustre-validate"p"*/if(p!=*tarrayp||p->pid!=pid)break;}out_unlock:read_unlock(&tasklist_lock);out:returnretval;}/**pro
c/fs/generic.c---genericroutinesfortheproc-fs**Thisfilecontainsgenericproc-fsroutinesforhandling*directoriesandfiles.**Copyright(C)1991,1992LinusTorvalds.*Copyright(C)1997TheodoreTs'o*/#include<asm/uaccess.h>#include<linux/errno.h>#include<linux/sche
d.h>#include<linux/proc_fs.h>#include<linux/stat.h>#include<asm/bitops.h>externstructinode_operationsproc_dyna_dir_inode_operations;staticssize_tproc_file_read(structfile*file,char*buf,size_tnbytes,loff_t*ppos);staticssize_tproc_file_write(structfile
*file,constchar*buffer,size_tcount,loff_t*ppos);staticlonglongproc_file_lseek(structfile*,longlong,int);intproc_match(intlen,constchar*name,structproc_dir_entry*de){if(!de||!de->low_ino)return0;if(de->namelen!=len)return0;return!memcmp(name,de->name,
len);}staticstructfile_operationsproc_file_operations={proc_file_lseek,/*lseek*/proc_file_read,/*read*/proc_file_write,/*write*/NULL,/*readdir*/NULL,/*poll*/NULL,/*ioctl*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecod
e*/NULL/*can'tfsync*/};structinode_operationsproc_file_inode_operations={&proc_file_operations,/*defaultprocfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/N
ULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};/**compatibilitytoreplacefs/proc/net.c*/structinode_operationsproc_net_inode_operations={&proc_file_operations,/*defaultnetfile-o
ps*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permiss
ion*/};#ifndefMIN#defineMIN(a,b)(((a)<(b))?(a):(b))#endif/*4Kpagesizebutouroutputroutinesusesomeslackforoverruns*/#definePROC_BLOCK_SIZE(3*1024)staticssize_tproc_file_read(structfile*file,char*buf,size_tnbytes,loff_t*ppos){structinode*inode=file->f_d
entry->d_inode;char*page;ssize_tretval=0;inteof=0;ssize_tn,count;char*start;structproc_dir_entry*dp;dp=(structproc_dir_entry*)inode->u.generic_ip;if(!(page=(char*)__get_free_page(GFP_KERNEL)))return-ENOMEM;while((nbytes>0)&&!eof){count=MIN(PROC_BLOCK
_SIZE,nbytes);start=NULL;if(dp->get_info){/**Handlebackwardscompatibilitywiththeoldnet*routines.**XXXWhatgiveswiththefile->f_flags&O_ACCMODE*test?Seemsstupidtome....*/n=dp->get_info(page,&start,*ppos,count,(file->f_flags&O_ACCMODE)==O_RDWR);if(n<coun
t)eof=1;}elseif(dp->read_proc){n=dp->read_proc(page,&start,*ppos,count,&eof,dp->data);}elsebreak;if(!start){/**Forprocfilesthatarelessthan4k*/start=page+*ppos;n-=*ppos;if(n<=0)break;if(n>count)n=count;}if(n==0)break;/*Endoffile*/if(n<0){if(retval==0)
retval=n;break;}/*Thisisahacktoallowmanglingoffileposindependent*ofactualbytesread.Simplyplacethedataatpage,*returnthebytes,andset`start'tothedesiredoffset*asanunsignedint.-Paul.Russell@rustcorp.com.au*/n-=copy_to_user(buf,start<page?page:start,n);if
(n==0){if(retval==0)retval=-EFAULT;break;}*ppos+=start<page?(long)start:n;/*Movedownthefile*/nbytes-=n;buf+=n;retval+=n;}free_page((unsignedlong)page);returnretval;}staticssize_tproc_file_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos
){structinode*inode=file->f_dentry->d_inode;structproc_dir_entry*dp;dp=(structproc_dir_entry*)inode->u.generic_ip;if(!dp->write_proc)return-EIO;/*FIXME:doesthisroutineneedppos?probably...*/returndp->write_proc(file,buffer,count,dp->data);}staticlongl
ongproc_file_lseek(structfile*file,longlongoffset,intorig){switch(orig){case0:if(offset<0)return-EINVAL;file->f_pos=offset;return(file->f_pos);case1:if(offset+file->f_pos<0)return-EINVAL;file->f_pos+=offset;return(file->f_pos);case2:return(-EINVAL);d
efault:return(-EINVAL);}}/**Thisfunctionparsesanamesuchas"tty/driver/serial",and*returnsthestructproc_dir_entryfor"/proc/tty/driver",and*returns"serial"inresidual.*/staticintxlate_proc_name(constchar*name,structproc_dir_entry**ret,constchar**residual
){constchar*cp=name,*next;structproc_dir_entry*de;intlen;de=&proc_root;while(1){next=strchr(cp,'/');if(!next)break;len=next-cp;for(de=de->subdir;de;de=de->next){if(proc_match(len,cp,de))break;}if(!de)return-ENOENT;cp+=len+1;}*residual=cp;*ret=de;retu
rn0;}structproc_dir_entry*create_proc_entry(constchar*name,mode_tmode,structproc_dir_entry*parent){structproc_dir_entry*ent=NULL;constchar*fn=name;intlen;if(!parent&&xlate_proc_name(name,&parent,&fn)!=0)gotoout;len=strlen(fn);ent=kmalloc(sizeof(struc
tproc_dir_entry)+len+1,GFP_KERNEL);if(!ent)gotoout;memset(ent,0,sizeof(structproc_dir_entry));memcpy(((char*)ent)+sizeof(*ent),fn,len+1);ent->name=((char*)ent)+sizeof(*ent);ent->namelen=len;if(S_ISDIR(mode)){if((mode&S_IALLUGO)==0)mode|=S_IRUGO|S_IXU
GO;ent->ops=&proc_dyna_dir_inode_operations;ent->nlink=2;}else{if((mode&S_IFMT)==0)mode|=S_IFREG;if((mode&S_IALLUGO)==0)mode|=S_IRUGO;ent->nlink=1;}ent->mode=mode;proc_register(parent,ent);out:returnent;}externvoidfree_proc_entry(structproc_dir_entry
*);voidfree_proc_entry(structproc_dir_entry*de){intino=de->low_ino;if(ino>=PROC_DYNAMIC_FIRST&&ino<PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)kfree(de);}/**Removea/procentryandfreeitifit'snotcurrentlyinuse.*Ifitisinuse,wesetthe'deleted'flag.*/voidremove_proc_e
ntry(constchar*name,structproc_dir_entry*parent){structproc_dir_entry*de;constchar*fn=name;intlen;if(!parent&&xlate_proc_name(name,&parent,&fn)!=0)gotoout;len=strlen(fn);for(de=parent->subdir;de;de=de->next){if(proc_match(len,fn,de))break;}if(de){pro
c_unregister(parent,de->low_ino);de->nlink=0;de->deleted=1;if(!de->count)free_proc_entry(de);else{printk("remove_proc_entry:%s/%sbusy,count=%d\n",parent->name,de->name,de->count);}}out:return;}/**linux/fs/proc/inode.c**Copyright(C)1991,1992LinusTorva
lds*/#include<linux/sched.h>#include<linux/proc_fs.h>#include<linux/kernel.h>#include<linux/mm.h>#include<linux/string.h>#include<linux/stat.h>#include<linux/file.h>#include<linux/locks.h>#include<linux/limits.h>#include<linux/config.h>#include<asm/s
ystem.h>#include<asm/uaccess.h>externvoidfree_proc_entry(structproc_dir_entry*);structproc_dir_entry*de_get(structproc_dir_entry*de){if(de)de->count++;returnde;}/**Decrementstheusecountandchecksfordeferreddeletion.*/voidde_put(structproc_dir_entry*de
){if(de){if(!de->count){printk("de_put:entry%salreadyfree!\n",de->name);return;}if(!--de->count){if(de->deleted){printk("de_put:deferreddeleteof%s\n",de->name);free_proc_entry(de);}}}}staticvoidproc_put_inode(structinode*inode){#ifdefCONFIG_SUN_OPENP
ROMFS_MODULEif((inode->i_ino>=PROC_OPENPROM_FIRST)&&(inode->i_ino<PROC_OPENPROM_FIRST+PROC_NOPENPROM)&&proc_openprom_use)(*proc_openprom_use)(inode,0);#endif/**Killoffunusedinodes...VFSwillunhashand*deletetheinodeifweseti_nlinktozero.*/if(inode->i_co
unt==1)inode->i_nlink=0;}/**Decrementtheusecountoftheproc_dir_entry.*/staticvoidproc_delete_inode(structinode*inode){structproc_dir_entry*de=inode->u.generic_ip;#ifdefined(CONFIG_SUN_OPENPROMFS)||defined(CONFIG_SUN_OPENPROMFS_MODULE)if((inode->i_ino>
=PROC_OPENPROM_FIRST)&&(inode->i_ino<PROC_OPENPROM_FIRST+PROC_NOPENPROM))return;#endifif(de){/**Callthefill_inodehooktoreleasemodulecounts.*/if(de->fill_inode)de->fill_inode(inode,0);de_put(de);}}staticstructsuper_operationsproc_sops={proc_read_inode
,proc_write_inode,proc_put_inode,proc_delete_inode,/*delete_inode(structinode*)*/NULL,NULL,NULL,proc_statfs,NULL};staticintparse_options(char*options,uid_t*uid,gid_t*gid){char*this_char,*value;*uid=current->uid;*gid=current->gid;if(!options)return1;f
or(this_char=strtok(options,",");this_char;this_char=strtok(NULL,",")){if((value=strchr(this_char,'='))!=NULL)*value++=0;if(!strcmp(this_char,"uid")){if(!value||!*value)return0;*uid=simple_strtoul(value,&value,0);if(*value)return0;}elseif(!strcmp(thi
s_char,"gid")){if(!value||!*value)return0;*gid=simple_strtoul(value,&value,0);if(*value)return0;}elsereturn1;}return1;}/**Thestandardrules,copiedfromfs/namei.c:permission().*/staticintstandard_permission(structinode*inode,intmask){intmode=inode->i_mo
de;if((mask&S_IWOTH)&&IS_RDONLY(inode)&&(S_ISREG(mode)||S_ISDIR(mode)||S_ISLNK(mode)))return-EROFS;/*Nobodygetswriteaccesstoaread-onlyfs*/elseif((mask&S_IWOTH)&&IS_IMMUTABLE(inode))return-EACCES;/*Nobodygetswriteaccesstoanimmutablefile*/elseif(curren
t->fsuid==inode->i_uid)mode>>=6;elseif(in_group_p(inode->i_gid))mode>>=3;if(((mode&mask&S_IRWXO)==mask)||capable(CAP_DAC_OVERRIDE))return0;/*readandsearchaccess*/if((mask==S_IROTH)||(S_ISDIR(inode->i_mode)&&!(mask&~(S_IROTH|S_IXOTH))))if(capable(CAP_
DAC_READ_SEARCH))return0;return-EACCES;}/**Setuppermissionrulesforprocesseslookingatotherprocesses.*You'renotallowedtoseeaprocessunlessithasthesameormore*restrictedrootthanyourown.Thispreventsachrootedprocesses*fromescapingthroughthe/procentriesofles
srestricted*processes,andthusallows/proctobesafelymountedinachrooted*area.**Notethatroot(uid0)doesn'tgetpermissionforthiseither,*sincechrootisstrongerthanroot.**XXXTODO:usethedentrymechanismtomakeoff-limitsprocssimply*invisibleratherthandenied?Doesea
chnamespacerootgetitsown*dentrytree?**Thisalsoappliesthedefaultpermissionschecks,asitonlyadds*restrictions.**JeremyFitzhardinge<jeremy@zip.com.au>*/intproc_permission(structinode*inode,intmask){structtask_struct*p;unsignedlongino=inode->i_ino;unsigne
dlongpid;structdentry*de,*base;if(standard_permission(inode,mask)!=0)return-EACCES;/**Findtherootoftheprocessesbeingexamined(ifany).*XXXSurelythere'sabetterwayofdoingthis?*/if(ino>=PROC_OPENPROM_FIRST&&ino<PROC_OPENPROM_FIRST+PROC_NOPENPROM)return0;/
*alreadyallowed*/pid=ino>>16;if(pid==0)return0;/*alreadyallowed*/de=NULL;base=current->fs->root;read_lock(&tasklist_lock);p=find_task_by_pid(pid);if(p&&p->fs)de=p->fs->root;read_unlock(&tasklist_lock);/*FIXME!*/if(p==NULL)return-EACCES;/*ENOENT?*/if(
de==NULL){/*kswapdandbdflushdon'thaveproperrootorcwd...*/return-EACCES;}/*XXXlocking?*/for(;;){structdentry*parent;if(de==base)return0;/*alreadyallowed*/de=de->d_covers;parent=de->d_parent;if(de==parent)break;de=parent;}return-EACCES;/*incompatiblero
ots*/}structinode*proc_get_inode(structsuper_block*sb,intino,structproc_dir_entry*de){structinode*inode;/**Incrementtheusecountsothedirentrycan'tdisappear.*/de_get(de);#if1/*shouldn'teverhappen*/if(de&&de->deleted)printk("proc_iget:usingdeletedentry%
s,count=%d\n",de->name,de->count);#endifinode=iget(sb,ino);if(!inode)gotoout_fail;#ifdefCONFIG_SUN_OPENPROMFS_MODULEif((inode->i_ino>=PROC_OPENPROM_FIRST)&&(inode->i_ino<PROC_OPENPROM_FIRST+PROC_NOPENPROM)&&proc_openprom_use)(*proc_openprom_use)(inod
e,1);#endif/*N.B.Howcanthistesteverfail??*/if(inode->i_sb!=sb)printk("proc_get_inode:inodefubar\n");inode->u.generic_ip=(void*)de;if(de){if(de->mode){inode->i_mode=de->mode;inode->i_uid=de->uid;inode->i_gid=de->gid;}if(de->size)inode->i_size=de->size
;if(de->ops)inode->i_op=de->ops;if(de->nlink)inode->i_nlink=de->nlink;/**Thefill_inoderoutineshouldusethiscall*toincrementmodulecounts,ifnecessary.*/if(de->fill_inode)de->fill_inode(inode,1);}/**Fixuptherootinode'snlinkvalue*/if(inode->i_ino==PROC_RO
OT_INO){structtask_struct*p;read_lock(&tasklist_lock);for_each_task(p){if(p->pid)inode->i_nlink++;}read_unlock(&tasklist_lock);}out:returninode;out_fail:de_put(de);gotoout;}structsuper_block*proc_read_super(structsuper_block*s,void*data,intsilent){st
ructinode*root_inode;lock_super(s);s->s_blocksize=1024;s->s_blocksize_bits=10;s->s_magic=PROC_SUPER_MAGIC;s->s_op=&proc_sops;root_inode=proc_get_inode(s,PROC_ROOT_INO,&proc_root);if(!root_inode)gotoout_no_root;s->s_root=d_alloc_root(root_inode,NULL);
if(!s->s_root)gotoout_no_root;parse_options(data,&root_inode->i_uid,&root_inode->i_gid);unlock_super(s);returns;out_no_root:printk("proc_read_super:getrootinodefailed\n");iput(root_inode);s->s_dev=0;unlock_super(s);returnNULL;}intproc_statfs(structsu
per_block*sb,structstatfs*buf,intbufsiz){structstatfstmp;tmp.f_type=PROC_SUPER_MAGIC;tmp.f_bsize=PAGE_SIZE/sizeof(long);tmp.f_blocks=0;tmp.f_bfree=0;tmp.f_bavail=0;tmp.f_files=0;tmp.f_ffree=0;tmp.f_namelen=NAME_MAX;returncopy_to_user(buf,&tmp,bufsiz)
?-EFAULT:0;}voidproc_read_inode(structinode*inode){unsignedlongino,pid;structtask_struct*p;inode->i_mtime=inode->i_atime=inode->i_ctime=CURRENT_TIME;inode->i_blocks=0;inode->i_blksize=1024;ino=inode->i_ino;if(ino>=PROC_OPENPROM_FIRST&&ino<PROC_OPENPR
OM_FIRST+PROC_NOPENPROM)gotoout;inode->i_op=NULL;inode->i_mode=0;inode->i_uid=0;inode->i_gid=0;inode->i_nlink=1;inode->i_size=0;pid=ino>>16;if(!pid)gotoout;read_lock(&tasklist_lock);p=find_task_by_pid(pid);if(!p)gotoout_unlock;ino&=0x0000ffff;if(ino=
=PROC_PID_INO||p->dumpable){inode->i_uid=p->euid;inode->i_gid=p->egid;}if(ino&PROC_PID_FD_DIR){structfile*file;ino&=0x7fff;file=fcheck_task(p,ino);if(!file)gotoout_unlock;inode->i_op=&proc_link_inode_operations;inode->i_size=64;inode->i_mode=S_IFLNK;
if(file->f_mode&1)inode->i_mode|=S_IRUSR|S_IXUSR;if(file->f_mode&2)inode->i_mode|=S_IWUSR|S_IXUSR;}out_unlock:/*Deferunlockinguntilwe'redonewiththetask*/read_unlock(&tasklist_lock);out:return;}voidproc_write_inode(structinode*inode){}/**linux/fs/proc
/kmsg.c**Copyright(C)1992byLinusTorvalds**/#include<linux/types.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/kernel.h>#include<linux/poll.h>#include<asm/uaccess.h>#include<asm/io.h>externunsignedlonglog_size;externstructwait_queue*l
og_wait;externintdo_syslog(inttype,char*bug,intcount);staticintkmsg_open(structinode*inode,structfile*file){returndo_syslog(1,NULL,0);}staticintkmsg_release(structinode*inode,structfile*file){(void)do_syslog(0,NULL,0);return0;}staticssize_tkmsg_read(
structfile*file,char*buf,size_tcount,loff_t*ppos){returndo_syslog(2,buf,count);}staticunsignedintkmsg_poll(structfile*file,poll_table*wait){poll_wait(file,&log_wait,wait);if(log_size)returnPOLLIN|POLLRDNORM;return0;}staticstructfile_operationsproc_km
sg_operations={NULL,/*kmsg_lseek*/kmsg_read,NULL,/*kmsg_write*/NULL,/*kmsg_readdir*/kmsg_poll,/*kmsg_poll*/NULL,/*kmsg_ioctl*/NULL,/*mmap*/kmsg_open,NULL,/*flush*/kmsg_release,NULL/*can'tfsync*/};structinode_operationsproc_kmsg_inode_operations={&pro
c_kmsg_operations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepag
e*/NULL,/*bmap*/NULL,/*truncate*/NULL/*permission*/};/**linux/fs/proc/link.c**Copyright(C)1991,1992LinusTorvalds**/proclink-filehandlingcode*/#include<asm/uaccess.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/mm.h>#include<linux/fs.h
>#include<linux/file.h>#include<linux/proc_fs.h>#include<linux/stat.h>staticintproc_readlink(structdentry*,char*,int);staticstructdentry*proc_follow_link(structdentry*,structdentry*,unsignedint);/**linkscan'tdomuch...*/staticstructfile_operationsproc
_fd_link_operations={NULL,/*lseek-default*/NULL,/*read-bad*/NULL,/*write-bad*/NULL,/*readdir-bad*/NULL,/*poll-default*/NULL,/*ioctl-default*/NULL,/*mmap*/NULL,/*veryspecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};struc
tinode_operationsproc_link_inode_operations={&proc_fd_link_operations,/*file-operations*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/proc_readlink,/*readlink*/proc
_follow_link,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/proc_permission/*permission*/};staticstructdentry*proc_follow_link(structdentry*dentry,structdentry*base,unsignedintfollow){structinode*inode=dentry->d_inode
;structtask_struct*p;structdentry*result;intino,pid;interror;/*Wedon'tneedabasepointerinthe/procfilesystem*/dput(base);error=permission(inode,MAY_EXEC);result=ERR_PTR(error);if(error)gotoout;ino=inode->i_ino;pid=ino>>16;ino&=0x0000ffff;result=ERR_PTR
(-ENOENT);read_lock(&tasklist_lock);p=find_task_by_pid(pid);if(!p)gotoout_unlock;switch(ino){casePROC_PID_CWD:if(!p->fs||!p->fs->pwd)gotoout_unlock;result=p->fs->pwd;gotoout_dget;casePROC_PID_ROOT:if(!p->fs||!p->fs->root)gotoout_unlock;result=p->fs->
root;gotoout_dget;casePROC_PID_EXE:{structvm_area_struct*vma;if(!p->mm)gotoout_unlock;vma=p->mm->mmap;while(vma){if((vma->vm_flags&VM_EXECUTABLE)&&vma->vm_file){result=vma->vm_file->f_dentry;gotoout_dget;}vma=vma->vm_next;}gotoout_unlock;}default:if(
ino&PROC_PID_FD_DIR){structfile*file;ino&=0x7fff;file=fcheck_task(p,ino);if(!file||!file->f_dentry)gotoout_unlock;result=file->f_dentry;gotoout_dget;}}out_dget:result=dget(result);out_unlock:read_unlock(&tasklist_lock);out:returnresult;}/**Thispretty
-printsthepathnameofadentry,*clarifyingsocketsetc.*/staticintdo_proc_readlink(structdentry*dentry,char*buffer,intbuflen){structinode*inode;char*tmp=(char*)__get_free_page(GFP_KERNEL),*path,*pattern;intlen;if(tmp==NULL)return-ENOMEM;/*Checkforspeciald
entries..*/pattern=NULL;inode=dentry->d_inode;if(inode&&dentry->d_parent==dentry){if(S_ISSOCK(inode->i_mode))pattern="socket:[%lu]";if(S_ISFIFO(inode->i_mode))pattern="pipe:[%lu]";}if(pattern){len=sprintf(tmp,pattern,inode->i_ino);path=tmp;}else{path
=d_path(dentry,tmp,PAGE_SIZE);len=tmp+PAGE_SIZE-1-path;}if(len<buflen)buflen=len;dput(dentry);copy_to_user(buffer,path,buflen);free_page((unsignedlong)tmp);returnbuflen;}staticintproc_readlink(structdentry*dentry,char*buffer,intbuflen){interror;dentr
y=proc_follow_link(dentry,NULL,1);error=PTR_ERR(dentry);if(!IS_ERR(dentry)){error=-ENOENT;if(dentry){error=do_proc_readlink(dentry,buffer,buflen);}}returnerror;}/**linux/fs/proc/mem.c**Copyright(C)1991,1992LinusTorvalds*/#include<linux/types.h>#inclu
de<linux/errno.h>#include<linux/sched.h>#include<linux/kernel.h>#include<linux/mm.h>#include<linux/proc_fs.h>#include<linux/bigmem.h>#include<asm/page.h>#include<asm/uaccess.h>#include<asm/io.h>#include<asm/pgtable.h>/**mem_writeisn'treallyagoodidear
ightnow.Itneeds*tocheckalotmore:iftheprocesswetrytowriteto*diesinthemiddlerightnow,mem_writewilloverwrite*kernelmemory..Thisdisablesitaltogether.*/#definemem_writeNULLstaticintcheck_range(structmm_struct*mm,unsignedlongaddr,intcount){structvm_area_st
ruct*vma;intretval;vma=find_vma(mm,addr);if(!vma)return-EACCES;if(vma->vm_start>addr)return-EACCES;if(!(vma->vm_flags&VM_READ))return-EACCES;while((retval=vma->vm_end-addr)<count){structvm_area_struct*next=vma->vm_next;if(!next)break;if(vma->vm_end!=
next->vm_start)break;if(!(next->vm_flags&VM_READ))break;vma=next;}if(retval>count)retval=count;returnretval;}staticstructtask_struct*get_task(intpid){structtask_struct*tsk=current;if(pid!=tsk->pid){tsk=find_task_by_pid(pid);/*Allowaccessesonlyunderth
esamecircumstances*thatwewouldallowptracetowork.*/if(tsk){if(!(tsk->flags&PF_PTRACED)||tsk->state!=TASK_STOPPED||tsk->p_pptr!=current)tsk=NULL;}}returntsk;}staticssize_tmem_read(structfile*file,char*buf,size_tcount,loff_t*ppos){structinode*inode=file
->f_dentry->d_inode;pgd_t*page_dir;pmd_t*page_middle;pte_tpte;char*page;structtask_struct*tsk;unsignedlongaddr;char*tmp;ssize_tscount,i;read_lock(&tasklist_lock);tsk=get_task(inode->i_ino>>16);read_unlock(&tasklist_lock);/*FIXME:Thisshouldreallybedon
eonlyafetrnotusingtskanymore!!!*/if(!tsk)return-ESRCH;addr=*ppos;scount=check_range(tsk->mm,addr,count);if(scount<0)returnscount;tmp=buf;while(scount>0){if(signal_pending(current))break;page_dir=pgd_offset(tsk->mm,addr);if(pgd_none(*page_dir))break;i
f(pgd_bad(*page_dir)){printk("Badpagedirentry%08lx\n",pgd_val(*page_dir));pgd_clear(page_dir);break;}page_middle=pmd_offset(page_dir,addr);if(pmd_none(*page_middle))break;if(pmd_bad(*page_middle)){printk("Badpagemiddleentry%08lx\n",pmd_val(*page_midd
le));pmd_clear(page_middle);break;}pte=*pte_offset(page_middle,addr);if(!pte_present(pte))break;page=(char*)pte_page(pte)+(addr&~PAGE_MASK);i=PAGE_SIZE-(addr&~PAGE_MASK);if(i>scount)i=scount;page=(char*)kmap((unsignedlong)page,KM_READ);copy_to_user(t
mp,page,i);kunmap((unsignedlong)page,KM_READ);addr+=i;tmp+=i;scount-=i;}*ppos=addr;returntmp-buf;}#ifndefmem_writestaticssize_tmem_write(structfile*file,char*buf,size_tcount,loff_t*ppos){structinode*inode=file->f_dentry->d_inode;pgd_t*page_dir;pmd_t*
page_middle;pte_tpte;char*page;structtask_struct*tsk;unsignedlongaddr;char*tmp;longi;addr=*ppos;tsk=get_task(inode->i_ino>>16);if(!tsk)return-ESRCH;tmp=buf;while(count>0){if(signal_pending(current))break;page_dir=pgd_offset(tsk,addr);if(pgd_none(*pag
e_dir))break;if(pgd_bad(*page_dir)){printk("Badpagedirentry%08lx\n",pgd_val(*page_dir));pgd_clear(page_dir);break;}page_middle=pmd_offset(page_dir,addr);if(pmd_none(*page_middle))break;if(pmd_bad(*page_middle)){printk("Badpagemiddleentry%08lx\n",pmd_
val(*page_middle));pmd_clear(page_middle);break;}pte=*pte_offset(page_middle,addr);if(!pte_present(pte))break;if(!pte_write(pte))break;page=(char*)pte_page(pte)+(addr&~PAGE_MASK);i=PAGE_SIZE-(addr&~PAGE_MASK);if(i>count)i=count;page=(unsignedlong)kma
p((unsignedlong)page,KM_WRITE);copy_from_user(page,tmp,i);kunmap((unsignedlong)page,KM_WRITE);addr+=i;tmp+=i;count-=i;}*ppos=addr;if(tmp!=buf)returntmp-buf;if(signal_pending(current))return-ERESTARTSYS;return0;}#endifstaticlonglongmem_lseek(structfil
e*file,longlongoffset,intorig){switch(orig){case0:break;case1:offset+=file->f_pos;break;default:return-EINVAL;}if(offset<0)return-EINVAL;file->f_pos=offset;returnoffset;}/**Thisisn'treallyreliablebyanymeans..*/intmem_mmap(structfile*file,structvm_are
a_struct*vma){structtask_struct*tsk;pgd_t*src_dir,*dest_dir;pmd_t*src_middle,*dest_middle;pte_t*src_table,*dest_table;unsignedlongstmp,dtmp,mapnr;structvm_area_struct*src_vma=NULL;structinode*inode=file->f_dentry->d_inode;/*Getthesource'staskinformat
ion*/tsk=get_task(inode->i_ino>>16);if(!tsk)return-ESRCH;/*Ensurethatwehaveavalidsourcearea.(Hastobemmap'edandhavevalidpageinformation.)Wecan'tmapsharedmemoryatthemomentbecauseworkingoutthevm_area_struct&nattachstuffisn'tworthit.*/src_vma=tsk->mm->mm
ap;stmp=vma->vm_offset;while(stmp<vma->vm_offset+(vma->vm_end-vma->vm_start)){while(src_vma&&stmp>src_vma->vm_end)src_vma=src_vma->vm_next;if(!src_vma||(src_vma->vm_flags&VM_SHM))return-EINVAL;src_dir=pgd_offset(tsk->mm,stmp);if(pgd_none(*src_dir))re
turn-EINVAL;if(pgd_bad(*src_dir)){printk("Badsourcepagedirentry%08lx\n",pgd_val(*src_dir));return-EINVAL;}src_middle=pmd_offset(src_dir,stmp);if(pmd_none(*src_middle))return-EINVAL;if(pmd_bad(*src_middle)){printk("Badsourcepagemiddleentry%08lx\n",pmd
_val(*src_middle));return-EINVAL;}src_table=pte_offset(src_middle,stmp);if(pte_none(*src_table))return-EINVAL;if(stmp<src_vma->vm_start){if(!(src_vma->vm_flags&VM_GROWSDOWN))return-EINVAL;if(src_vma->vm_end-stmp>current->rlim[RLIMIT_STACK].rlim_cur)r
eturn-EINVAL;}stmp+=PAGE_SIZE;}src_vma=tsk->mm->mmap;stmp=vma->vm_offset;dtmp=vma->vm_start;flush_cache_range(vma->vm_mm,vma->vm_start,vma->vm_end);flush_cache_range(src_vma->vm_mm,src_vma->vm_start,src_vma->vm_end);while(dtmp<vma->vm_end){while(src_
vma&&stmp>src_vma->vm_end)src_vma=src_vma->vm_next;src_dir=pgd_offset(tsk->mm,stmp);src_middle=pmd_offset(src_dir,stmp);src_table=pte_offset(src_middle,stmp);dest_dir=pgd_offset(current->mm,dtmp);dest_middle=pmd_alloc(dest_dir,dtmp);if(!dest_middle)r
eturn-ENOMEM;dest_table=pte_alloc(dest_middle,dtmp);if(!dest_table)return-ENOMEM;if(!pte_present(*src_table)){if(handle_mm_fault(tsk,src_vma,stmp,1)<0)return-ENOMEM;}if((vma->vm_flags&VM_WRITE)&&!pte_write(*src_table)){if(handle_mm_fault(tsk,src_vma,
stmp,1)<0)return-ENOMEM;}set_pte(src_table,pte_mkdirty(*src_table));set_pte(dest_table,*src_table);mapnr=MAP_NR(pte_page(*src_table));if(mapnr<max_mapnr)atomic_inc(&mem_map[MAP_NR(pte_page(*src_table))].count);stmp+=PAGE_SIZE;dtmp+=PAGE_SIZE;}flush_t
lb_range(vma->vm_mm,vma->vm_start,vma->vm_end);flush_tlb_range(src_vma->vm_mm,src_vma->vm_start,src_vma->vm_end);return0;}staticstructfile_operationsproc_mem_operations={mem_lseek,mem_read,mem_write,NULL,/*mem_readdir*/NULL,/*mem_poll*/NULL,/*mem_ioc
tl*/mem_mmap,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};structinode_operationsproc_mem_inode_operations={&proc_mem_operations,/*defaultbasedirectoryfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*l
ink*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL,/*truncate*/proc_permission/*permission*/};/**linux/fs/proc/net.c**
Copyright(C)1991,1992LinusTorvalds**gjh3/'93heim@peanuts.informatik.uni-tuebingen.de(GeraldJ.Heim)*mostofthisfileisstolenfrombase.c*itworks,butyoushouldn'tuseitasaguideline*fornewproc-fsentries.oncei'llmakeitbetter.*fvk3/'93waltje@uwalt.nl.mugnet.org
(FredN.vanKempen)*cleanedupthewholething,moved"net"specificcodeto*theNETkernellayer(whereitbelongedinthefirstplace).*MichaelK.Johnson(johnsonm@stolaf.edu)3/93*Addedsupportfrommypreviousinet.c.Cleanedthingsup*quiteabit,modularizedthecode.*fvk4/'93walt
je@uwalt.nl.mugnet.org(FredN.vanKempen)*Renamed"route_get_info()"to"rt_get_info()"forconsistency.*AlanCox(gw4pts@gw4pts.ampr.org)4/94*DustedoffthecodeandaddedIPX.Fixedthe4Klimit.*ErikSchoenfelder(schoenfr@ibr.cs.tu-bs.de)*/proc/net/snmp.*AlanCox(gw4p
ts@gw4pts.ampr.org)1/95*AddedAppleTalkslots**procnetdirectoryhandlingfunctions*/#include<linux/errno.h>#include<linux/sched.h>#include<linux/proc_fs.h>#include<linux/stat.h>#include<linux/fcntl.h>#include<linux/mm.h>#include<asm/uaccess.h>#definePROC
_BLOCK_SIZE(3*1024)/*4Kpagesizebutouroutputroutinesusesomeslackforoverruns*/staticlongproc_readnet(structinode*inode,structfile*file,char*buf,unsignedlongcount){char*page;intbytes=count;intcopied=0;char*start;structproc_dir_entry*dp;if(count<0)return
-EINVAL;dp=(structproc_dir_entry*)inode->u.generic_ip;if(!(page=(char*)__get_free_page(GFP_KERNEL)))return-ENOMEM;while(bytes>0){intlength,thistime=bytes;if(bytes>PROC_BLOCK_SIZE)thistime=PROC_BLOCK_SIZE;length=dp->get_info(page,&start,file->f_pos,th
istime,(file->f_flags&O_ACCMODE)==O_RDWR);/**Wehavebeengivenanonpagealignedblockof*thedataweaskedfor+abit.Wehavebeengiven*thestartpointerandweknowthelength..*/if(length<=0)break;/**Copythebytes*/copy_to_user(buf+copied,start,length);file->f_pos+=leng
th;/*Movedownthefile*/bytes-=length;copied+=length;if(length<thistime)break;/*Endoffile*/}free_page((unsignedlong)page);returncopied;}staticstructfile_operationsproc_net_operations={NULL,/*lseek-default*/proc_readnet,/*read-bad*/NULL,/*write-bad*/NUL
L,/*readdir*/NULL,/*poll-default*/NULL,/*ioctl-default*/NULL,/*mmap*/NULL,/*nospecialopencode*/NULL,/*flush*/NULL,/*nospecialreleasecode*/NULL/*can'tfsync*/};/**procdirectoriescandoalmostnothing..*/structinode_operationsproc_net_inode_operations={&pr
oc_net_operations,/*defaultnetfile-ops*/NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*
bmap*/NULL,/*truncate*/NULL/*permission*/};/**fs/proc/omirr.c-onlinemirrorsupport**(C)1997ThomasSchoebel-Theuer*/#include<linux/string.h>#include<linux/mm.h>#include<linux/fs.h>#include<linux/omirr.h>#include<asm/uaccess.h>staticintnr_omirr_open=0;st
aticintcleared_flag=0;staticchar*buffer=NULL;staticintread_pos,write_pos;staticintclip_pos,max_pos;staticstructwait_queue*read_wait=NULL;staticstructwait_queue*write_wait=NULL;static/*inline*/intreserve_write_space(intlen){intrest=max_pos-write_pos;i
f(rest<len){clip_pos=write_pos;write_pos=0;rest=max_pos;}while(read_pos>write_pos&&read_pos<=write_pos+len){if(!nr_omirr_open)return0;interruptible_sleep_on(&write_wait);}return1;}static/*inline*/voidwrite_space(intlen){write_pos+=len;wake_up_interru
ptible(&read_wait);}static/*inline*/intreserve_read_space(intlen){intrest=clip_pos-read_pos;if(!rest){read_pos=0;rest=clip_pos;clip_pos=max_pos;}if(len>rest)len=rest;while(read_pos==write_pos){interruptible_sleep_on(&read_wait);}rest=write_pos-read_p
os;if(rest>0&&rest<len)len=rest;returnlen;}static/*inline*/voidread_space(intlen){read_pos+=len;if(read_pos>=clip_pos){read_pos=0;clip_pos=max_pos;}wake_up_interruptible(&write_wait);}static/*inline*/voidinit_buffer(char*initxt){intlen=initxt?strlen(
initxt):0;if(!buffer){buffer=(char*)__get_free_page(GFP_USER);max_pos=clip_pos=PAGE_SIZE;}read_pos=write_pos=0;memcpy(buffer,initxt,len);write_space(len);}staticintomirr_open(structinode*inode,structfile*file){if(nr_omirr_open)return-EAGAIN;nr_omirr_
open++;if(!buffer)init_buffer(NULL);return0;}staticintomirr_release(structinode*inode,structfile*file){nr_omirr_open--;read_space(0);return0;}staticlongomirr_read(structinode*inode,structfile*file,char*buf,unsignedlongcount){char*tmp;intlen;interror=
0;if(!count)gotodone;error=-EINVAL;if(!buf||count<0)gotodone;error=verify_area(VERIFY_WRITE,buf,count);if(error)gotodone;error=-EAGAIN;if((file->f_flags&O_NONBLOCK)&&read_pos==write_pos)gotodone;error=len=reserve_read_space(count);tmp=buffer+read_pos
;while(len){put_user(*tmp++,buf++);len--;}read_space(error);done:returnerror;}intcompute_name(structdentry*entry,char*buf){intlen;if(IS_ROOT(entry)){*buf='/';return1;}len=compute_name(entry->d_parent,buf);if(len>1){buf[len++]='/';}memcpy(buf+len,entr
y->d_name,entry->d_len);returnlen+entry->d_len;}int_omirr_print(structdentry*ent1,structdentry*ent2,structqstr*suffix,constchar*fmt,va_listargs1,va_listargs2){intcount=strlen(fmt)+10;/*estimate*/constchar*tmp=fmt;charlenbuf[8];intres;if(!buffer)init_
buffer(NULL);while(*tmp){while(*tmp&&*tmp++!='%');if(*tmp){if(*tmp=='s'){char*str=va_arg(args1,char*);count+=strlen(str);}else{(void)va_arg(args1,int);count+=8;/*estimate*/}}}if(ent1){structdentry*dent=ent1;while(dent&&!IS_ROOT(dent)){count+=dent->d_
len+1;dent=dent->d_parent;}count++;if(ent2){dent=ent2;while(dent&&!IS_ROOT(dent)){count+=dent->d_len+1;dent=dent->d_parent;}count++;}if(suffix)count+=suffix->len+1;}if((nr_omirr_open|cleared_flag)&&reserve_write_space(count)){cleared_flag=0;res=vspri
ntf(buffer+write_pos+4,fmt,args2)+4;if(res>count)printk("omirr:formatestimatewaswrong\n");if(ent1){res+=compute_name(ent1,buffer+write_pos+res);if(ent2){buffer[write_pos+res++]='\0';res+=compute_name(ent2,buffer+write_pos+res);}if(suffix){buffer[writ
e_pos+res++]='/';memcpy(buffer+write_pos+res,suffix->name,suffix->len);res+=suffix->len;}buffer[write_pos+res++]='\0';buffer[write_pos+res++]='\n';}sprintf(lenbuf,"%04d",res);memcpy(buffer+write_pos,lenbuf,4);}else{if(!cleared_flag){cleared_flag=1;in
it_buffer("0007Z\n");}res=0;}write_space(res);returnres;}intomirr_print(structdentry*ent1,structdentry*ent2,structqstr*suffix,constchar*fmt,...){va_listargs1,args2;intres;/*Idon'tknowwhetherIcouldmakeasimplecopyoftheva_list,*soforthesafeway...*/va_st
art(args1,fmt);va_start(args2,fmt);res=_omirr_print(ent1,ent2,suffix,fmt,args1,args2);va_end(args2);va_end(args1);returnres;}intomirr_printall(structinode*inode,constchar*fmt,...){intres=0;structdentry*tmp=inode->i_dentry;if(tmp)do{va_listargs1,args2
;va_start(args1,fmt);va_start(args2,fmt);res+=_omirr_print(tmp,NULL,NULL,fmt,args1,args2);va_end(args2);va_end(args1);tmp=tmp->d_next;}while(tmp!=inode->i_dentry);returnres;}staticstructfile_operationsomirr_operations={NULL,/*omirr_lseek*/omirr_read,
NULL,/*omirr_write*/NULL,/*omirr_readdir*/NULL,/*omirr_select*/NULL,/*omirr_ioctl*/NULL,/*mmap*/omirr_open,NULL,/*flush*/omirr_release,NULL,/*fsync*/NULL,/*fasync*/NULL,/*check_media_change*/NULL/*revalidate*/};structinode_operationsproc_omirr_inode_
operations={&omirr_operations,NULL,/*create*/NULL,/*lookup*/NULL,/*link*/NULL,/*unlink*/NULL,/*symlink*/NULL,/*mkdir*/NULL,/*rmdir*/NULL,/*mknod*/NULL,/*rename*/NULL,/*readlink*/NULL,/*follow_link*/NULL,/*readpage*/NULL,/*writepage*/NULL,/*bmap*/NULL
,/*truncate*/NULL,/*permission*/NULL/*smap*/};/*$Id:openpromfs.c,v1.331999/04/2811:57:33davemExp$*openpromfs.c:/proc/openpromhandlingroutines**Copyright(C)1996-1998JakubJelinek(jj@sunsite.mff.cuni.cz)*Copyright(C)1998EddieC.Dost(ecd@skynet.be)*/#incl
ude<linux/module.h>#include<linux/types.h>#include<linux/string.h>#include<linux/fs.h>#include<linux/proc_fs.h>#include<linux/init.h>#include<asm/openprom.h>#include<asm/oplib.h>#include<asm/uaccess.h>#defineALIASES_NNODES64typedefstruct{u16parent;u1
6next;u16child;u16first_prop;u32node;}openpromfs_node;typedefstruct{#defineOPP_STRING0x10#defineOPP_STRINGLIST0x20#defineOPP_BINARY0x40#defineOPP_HEXSTRING0x80#defineOPP_DIRTY0x01#defineOPP_QUOTED0x02#defineOPP_NOTQUOTED0x04#defineOPP_ASCIIZ0x08u32fl
ag;u32alloclen;u32len;char*value;charname[8];}openprom_property;staticopenpromfs_node*nodes=NULL;staticintalloced=0;staticu16last_node=0;staticu16first_prop=0;staticu16options=0xffff;staticu16aliases=0xffff;staticintaliases_nodes=0;staticchar*alias_n
ames[ALIASES_NNODES];staticstructinode_operations*proc_openprom_iops=0;staticstructopenpromfs_dev**devices;#defineNODE(ino)nodes[ino-PROC_OPENPROM_FIRST]#defineNODE2INO(node)(node+PROC_OPENPROM_FIRST)#defineNODEP2INO(no)(no+PROC_OPENPROM_FIRST+last_n
ode)staticintopenpromfs_create(structinode*,structdentry*,int);staticintopenpromfs_readdir(structfile*,void*,filldir_t);staticstructdentry*openpromfs_lookup(structinode*,structdentry*dentry);staticintopenpromfs_unlink(structinode*,structdentry*dentry
);staticssize_tnodenum_read(structfile*file,char*buf,size_tcount,loff_t*ppos){structinode*inode=file->f_dentry->d_inode;charbuffer[10];if(count<0||!inode->u.generic_ip)return-EINVAL;sprintf(buffer,"%8.8x\n",(u32)(long)(inode->u.generic_ip));if(file->

Hosted by uCoz