linux下ls命令的C语言实现(实现大部分功能)_第1页
linux下ls命令的C语言实现(实现大部分功能)_第2页
linux下ls命令的C语言实现(实现大部分功能)_第3页
linux下ls命令的C语言实现(实现大部分功能)_第4页
linux下ls命令的C语言实现(实现大部分功能)_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

(完整word版)linux下ls命令的C语言实现(实现大部分功能)(完整word版)linux下ls命令的C语言实现(实现大部分功能):将两个文件h和c文件放入xc/可执行文件名-lsubuntu16.04List.h文件代码内容如下:#ifndef_LINUX_LIST_H#define_LINUX_LIST_H/*Simpledoublylinkedlistimplementation.*Someoftheinternalfunctions(" xxx")areusefulwhenmanipulatingwholelistsratherthansingleentries,assometimeswealreadyknowthenext/preventriesandwecangeneratebettercodebyusingthemdirectlyratherthanusingthegenericsingle-entryroutines.*/structlist_head{structlist_head*next,*prev;};#defineLIST_HEAD_INIT(name){&(name),&(name)}#defineLIST_HEAD(name)\structlist_headname=LIST_HEAD_INIT(name)#defineINIT_LIST_HEAD(ptr)do{\(ptr)->next=(ptr);(ptr)->prev=(ptr);\}while(0)/*Insertanewentrybetweentwoknownconsecutiveentries.*Thisisonlyforinternallistmanipulationwhereweknowtheprev/nextentriesalready!*/static inline void list_add(structlist_head*new,structlist_head*prev,structlist_head*next){next->prev=new;new->next=next;new->prev=prev;prev->next=new;}/**list_add-addanewentry@new:newentrytobeadded@head:listheadtoadditafter*Insertanewentryafterthespecifiedhead.Thisisgoodforimplementingstacks.*/static inline voidlist_add(structlist_head*new,structlist_head*head){ list_add(new,head,head->next);}/**list_add_tail-addanewentry@new:newentrytobeadded@head:listheadtoadditbefore*Insertanewentrybeforethespecifiedhead.Thisisusefulforimplementingqueues.*/static inline voidlist_add_tail(structlist_head*new,structlist_head*head){ list_add(new,head->prev,head);}/*Deletealistentrybymakingtheprev/nextentriespointtoeachother.*Thisisonlyforinternallistmanipulationwhereweknowtheprev/nextentriesalready!*/static inline void list_del(structlist_head*prev,structlist_head*next){next->prev=prev;prev->next=next;}/**list_del-deletesentryfromlist.@entry:theelementtodeletefromthelist.Note:list_emptyonentrydoesnotreturntrueafterthis,theentryisinanundefinedstate.*/static inline voidlist_del(structlist_head*entry){ list_del(entry->prev,entry->next);entry->next=entry->prev=0;}/**list_del_init-deletesentryfromlistandreinitializeit.@entry:theelementtodeletefromthelist.*/static inline voidlist_del_init(structlist_head*entry){ list_del(entry->prev,entry->next);INIT_LIST_HEAD(entry);}/**list_empty-testswhetheralistisempty@head:thelisttotest.*/static inline intlist_empty(structlist_head*head){returnhead->next==head;}/**list_splice-jointwolists@list:thenewlisttoadd.@head:theplacetoadditinthefirstlist.*/static inline voidlist_splice(structlist_head*list,structlist_head*head){structlist_head*first=list->next;if(first!=list){structlist_head*last=list->prev;structlist_head*at=head->next;first->prev=head;head->next=first;last->next=at;at->prev=last;}}/**list_entry-getthestructforthisentry@ptr: the&structlist_headpointer.@type: thetypeofthestructthisisembeddedin.@member: thenameofthelist_structwithinthestruct.*/#definelist_entry(ptr,type,member)\((type*)((char*)(ptr)-(unsignedlong)(&((type*)0)->member)))/**list_for_each- iterateoveralist@pos: the&structlist_headtouseasaloopcounter.@head:theheadforyourlist.*/#definelist_for_each(pos,head)\for(pos=(head)->next;pos!=(head);\pos=pos->next)/**list_for_each_safe - iterateoveralistsafeagainstremovaloflistentry@pos: the&structlist_headtouseasaloopcounter.@n: another&structlist_headtouseastemporarystorage@head:theheadforyourlist.*/#definelist_for_each_safe(pos,n,head)\for(pos=(head)->next,n=pos->next;pos!=(head);\pos=n,n=pos->next)#endifls.c文件内容如下:/*该文件简单模拟linux系统的ls命令(实现了大部份功能)功能需求(FIXME),实现的常用的选项:--help 显示帮助信息-a -l 显示详细信息-L 只打印链接文件名-r 反排序-R -c 以文件最后状态修改时间排序,st_ctime;//timeoflastchangei-node 最近一次被更改时间,此参数会在文件所有者、组、权限被更改时更新-t 以文件最后修改时间排序,st_mtime;//timeoflastmodification文件最后一次被修改的时间,一般只有在用mknod、utime和write时才会改变-u ;//timeoflastaccess文件最近一次被存取或被执行的时间,一般只有在用mknod、utime、read、write与tructate时改变-S 以文件大小排序-n -i I-h –human-readable以容易理解的格式列出文件大小(例如1K234M2G)FIXME:已知BUG:输出的格式与系统由一定差别文件与文件夹没有颜色区分*/#include<time.h>#include<stdio.h>#include<getopt.h>#include<errno.h>#include<string.h>#include<sys/stat.h>#include<dirent.h>#include<stdlib.h>#include<assert.h>#include<getopt.h>#include<pwd.h>#include<grp.h>#include<unistd.h>#include"list.h"#defineMAX_PATH 256 /**/#definePEER_MALLOC_FILE 64 /*当内存不够时,最少申请多少个structfile_info的大小避免频繁申请内存*//* sys/stat.h中structstat*//*structstat{dev_t st_dev;//device文件的设备编号ino_t st_ino;//inode文件的i-nodemode_t st_mode;//protection文件的类型和存取的权限nlink_t st_nlink;//numberofhardlinks连到该文件的硬连接数,刚建立的文件值为1.uid_t st_uid;//userIDofowner文件所有者的用户识别码gid_t st_gid;//groupIDofowner文件所有者的组识别码dev_t st_rdev;//devicetype若此文件为装置设备文,则为其设备编号off_t st_size;//totalsize,inbytes文件大小,以字节计算unsignedlong st_blksize;//blocksizeforfilesystemI/O文件系统的I/O缓冲区大小.unsignedlong st_blocks;//numberofblocksallocated 512个字节.time_t st_atime;//timeoflastaccess mknod、utime、write与tructate时改变.time_t st_mtime;//timeoflastmodification文件最后一次被修改的时间,一般只有在mknod、utime和write时才会改变time_t st_ctime;//timeoflastchangei-node 所有者、组、权限被更改时更新};*//*一个文件基本信息的节点*/structfile_info{charfil_name[MAX_PATH];/*文件名节点*/chardst_name[MAX_PATH]; /*链接文件名真实名*/charis_link;/*是否是链接文件1:是0:否*/structstatstatbuf;/*文件属性节点*/};/*一个目录的信息列表*/structdir_info{char dir_path[MAX_PATH]; /**/structfile_info *p_filenode; /*指向该目录下的文件信息内存类似于数组,之所以不采用链表 ,是为了好用qsort进行排序*/size_tused_size;/*已用了多少个strcutfile_info*/size_tfree_size;/*空余还有多少个strcutfile_info*/size_t dir_size; /*该目录的大小(单位为 k),用ls-l显示的第一total(总用量的值*/char need_print_total; /*total*/};/*等待遍历节点的节点*/structdir_list{char dir_path[MAX_PATH]; /*待遍历的目录节structlist_head list_node; /*链表节*/};structparam{char a; /*显示所有文件*/char l; /*显示详细信息*/char L; /*只显示链接文件*/charr;/*反排序*/charR;/*递归显示*/charc;/*状态修改时间排序*/chart;/*最后修改时间排序*/charu;/*最后访问时间排序*/charS;/*以文件大小排序*/charn;/*以文件名排序*/chari;/*显示I节点*/chard;/*显示每块大小*/charh;/*以k为单位显示*/charm;/*显示帮助信息*/};//全局typedefint(*COM_FUNC)(constvoid*,constvoid*);//定义了一个指向函数的指针COM_FUNC,其返回值int类型,参数也是后面的(constvoid*),接下来我们就可以直接使用COM_FUNC来定义这种指针变量,比如:COM_FUNCg_com_func;//等价于intg_com_func(constvoid*,constvoid*);structdir_info g_dir_info; /*当前正处理的目structparam g_param; /*传入参*/structlist_head g_dir_head; /*需要扫描目录的链表COM_FUNC g_com_func=NULL;/*帮助信息*/staticvoidprintf_usage(){printf("usage:\n");printf("--help showthehelpinfomation\n");printf("-a showallfiles\n");printf("-l showthedetailedinformation\n");printf("-L onlyshowlinknameifthefileislinkfile\n");printf("-r recursivedisplay\n");printf("-R Recursivedisplay\n");printf("-c sortbystatuschange\n");printf("-t sortbylastmodifytime\n");printf("-u sortbylastaccesstime\n");printf("-S sortbyfilesize\n");printf("-h –human-readabledisplay\n");printf("-n sortbyfilename,thedefault.Andifinputmorethanonesortway,onlysortbyfilename\n");printf("-i showi-nodeinfo\n");printf("-d showI/Oblocksize\n");}/*计算一个目录的大小,即ls-l显示出来的第一行"total"*/staticvoidcal_dir_size(){size_t i;structfile_info *p;g_dir_info.dir_size=0;g_dir_info.need_print_total=1; /*需要打印total字段标*/for(i=0;i<g_dir_info.used_size;++i) //used_size为size_t类型{p=g_dir_info.p_filenode+i;g_dir_info.dir_size+=p->statbuf.st_blksize*文件系统的I/O缓冲区大小 占用文件区块的个,每一区块大小为512个字节}/*换算为k*/g_dir_info.dir_size=g_dir_info.dir_size/1024/8;}/*程序带错误码退出*/staticvoiddead_errno(intno){assert(0);//在assert.h中,assert的作用是现计算表达式expression,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort来终止程序运行。exit(no);}/*FIXME内存追加方式申请内存*/staticvoidrealloc_file_info(structdir_info*dir_info){assert(dir_info!=NULL);assert(dir_info->free_size==0); /*没空闲内存了才会申size_t newsize; /*新内存的大小*/newsize=(dir_info->used_size+PEER_MALLOC_FILE)*sizeof(structfile_info);if((dir_info->p_filenode=realloc(dir_info->p_filenode,newsize))==NULL){/**perror()一般输出错误原因,参数为字符串*/perror("realloc");dead_errno(1);}dir_info->free_size+=PEER_MALLOC_FILE;}/*保存文件节点信息*/staticvoidsave_file_info(structdir_info*dir_info,structstat*stat,char*d_name,char*dst_name){assert(d_name!=NULL&&d_name[0]!=0);structfile_info *pfile_info=NULL;assert(dir_info!=NULL&&stat!=NULL);if(dir_info->p_filenode==NULL||dir_info->free_size==0)/*内存不够*/realloc_file_info(dir_info);pfile_info=dir_info->p_filenode+dir_info->used_size;strncpy(pfile_info->fil_name,d_name,MAX_PATH-1);memmove(&pfile_info->statbuf,stat,sizeof(structstat));if(dst_name!=NULL) /*d_name*/{pfile_info->is_link=1;strncpy(pfile_info->dst_name,dst_name,MAX_PATH-1);}else{pfile_info->is_link=0;pfile_info->dst_name[0]=0;}--(dir_info->free_size);++(dir_info->used_size);}/*添加目录*/staticvoidadd_dir(char*pdir,structlist_head*head){assert(pdir!=NULL&&pdir[0]!=0&&head!=NULL);structdir_list *pnode=NULL;if((pnode=(structdir_list*)malloc(sizeof(structdir_list)))==NULL){printf("mallocdir_listerror\n");exit(1);}memset(pnode,0,sizeof(structdir_list));strncpy(pnode->dir_path,pdir,MAX_PATH-1);list_add_tail(&pnode->list_node,head); //}/*以最后状态修改时间排序函数*/staticintcmp_last_statetime(constvoid*arg1,constvoid*arg2){structfile_info *p1=(structfile_info*)arg1;structfile_info *p2=(structfile_info*)arg2;returnp2->statbuf.st_ctime-p1->statbuf.st_ctime;}/*以文件最后修改时间排序函数*/staticintcmp_last_change(constvoid*arg1,constvoid*arg2){structfile_info *p1=(structfile_info*)arg1;structfile_info *p2=(structfile_info*)arg2;returnp2->statbuf.st_mtime-p1->statbuf.st_mtime;}/*以文件最后访问时间排序函数*/staticintcmp_last_accesstime(constvoid*arg1,constvoid*arg2){structfile_info *p1=(structfile_info*)arg1;structfile_info *p2=(structfile_info*)arg2;returnp2->statbuf.st_atime-p1->statbuf.st_atime;}/*以文件大小排序函数*/staticintcmp_filesize(constvoid*arg1,constvoid*arg2){structfile_info *p1=(structfile_info*)arg1;structfile_info *p2=(structfile_info*)arg2;returnp2->statbuf.st_size-p1->statbuf.st_size;}/*以文件名排序函数*/staticintcmp_filename(constvoid*arg1,constvoid*arg2){structfile_info *p1=(structfile_info*)arg1;structfile_info *p2=(structfile_info*)arg2;returnstrncasecmp(p1->fil_name,p2->fil_name,MAX_PATH);}/*排序*/staticvoidsort(structdir_info*dir_info){/*TODO*/assert(dir_info!=NULL);if(g_com_func!=NULL)/*快速排序voidqsort(void*base,size_tnmemb,size_tsize,int(*compar)(constvoid*,constvoid*))数组首地址数组元素个数元素占用内存空间指向函数的指针*/qsort(dir_info->p_filenode,dir_info->used_size,sizeof(structfile_info),g_com_func);}/*LINUX下历遍目录的方法:打开目录-》读取-》关闭目录相关函数是opendir->readdir->closediropendir()成功则返回DIR*型态的目录流,打开失败则返回NULL.#include<dirent.h>DIR*opendir(constchar*dirname);readdir()成功则返回下个目录进入点。有错误发生或读取到目录文件尾则返回NULL#include<dirent.h>structdirent*readdir(DIR*dirp);关闭成功则返回0,失败返回-1,错误原因存于errno中#include<dirent.h>intclosedir(DIR*dirp);*//*dirent的结构如下定义structdirent{longd_ino; //inodenumber索引节点号off_td_off; //offsettothisdirent在目录文件中的偏移unsignedshortd_reclen; //lengthofthisd_name文件名长unsignedchard_type; //thetypeofd_name文件类型chard_name[NAME_MAX+1]; //filename(null-terminated)文件名,最长255}*//*扫描一个目录下的所有文件*/staticintscan_adir(char*dir_name,structdir_info*dir_info){assert(dir_name!=NULL);assert(dir_info!=NULL);assert(strlen(dir_name)>0);structstat statbuf;//structstatstructdirent *dirp; //定义一个structdirent结构体指针变量DIR *dp;char *ptr; /**/char filename[MAX_PATH]={0};//错误检测处理if(lstat(dir_name,&statbuf)<0){perror("lstat");dead_errno(1);}if(S_ISDIR(statbuf.st_mode)==0)/*不是目录*/{printf("%sisnotadirectory\n",dir_name);assert(0);}strcpy(filename,dir_name);ptr=filename+strlen(dir_name);/*使目录始终带有/结束*/if(ptr[-1]!='/'){ptr[0]='/';++ptr;}/*保存该目录名*/strncpy(dir_info->dir_path,filename,MAX_PATH-1);/*下面是目录了*/if((dp=opendir(dir_name))==NULL){printf("opendir%serror:%s\n",dir_name,strerror(errno));return1;}while((dirp=readdir(dp))!=NULL){/*不显示所有信息,跳过隐藏文件(包括...)*/chara[255];strcpy(a,dirp->d_name);// printf("%c\n",a[0]);if(g_param.a==0&&(a[0]=='.'||strcmp(dirp->d_name,".")==0||strcmp(dirp->d_name,"..")==0))continue;*/strcpy(ptr,dirp->d_name);/*获取文件属性*/if(lstat(filename,&statbuf)<0){printf("lstat2file%serror:%s\n",ptr,strerror(errno));continue;}if(S_ISLNK(statbuf.st_mode))/*链接文件*/{char dst_name[MAX_PATH]={0};if(readlink(dirp->d_name,dst_name,MAX_PATH-1)<0){printf("readlinkfile%serror:%s\n",dirp->d_name,strerror(errno));continue;}save_file_info(dir_info,&statbuf,dirp->d_name,dst_name);}else{if(g_param.R&&S_ISDIR(statbuf.st_mode))add_dir(filename,&g_dir_head);save_file_info(dir_info,&statbuf,dirp->d_name,NULL);}}closedir(dp);/*排序*/sort(dir_info);return0;}/*得到用户选项参数FIXME:当用户输入的选项有冲突时,还没做错误性检测getopt被用来解析命令行选项参数*/staticintget_param(intargc,char*argv[]){char c;/*长选项--(第一项:名字,第二项:是否带参数0表示不带参数,第三项:填0,第四项:短选项名)*//*返回第四个数(如果第三个数为NULL,不然就返回0)*/staticstructoptionlong_options[]={{"help",0,0,'m'},//getopt_long返回'm'{0,0,0,0}};/*短参数定义-*/staticconstcharshort_options[]="alLrRctuSidnh";//-l-h-r-t-R...while(1){intoption_index=0;c=getopt_long(argc,argv,short_options,long_options,&option_index);//getopt_long既可以处理长选项,也可以处理短选项,无选项后返回-1if(c==-1)switch(c){case'm': /*g_param.m=1;return-1; /*case'h':break;case'a':g_param.a=1;break;case'l':g_param.l=1;break;case'L':g_param.L=1;break;case'r':g_param.r=1;break;case'R':g_param.R=1;break;case'c':g_param.c=1;break;case't':g_param.t=1;break;case'u':g_param.u=1;break;case'S':g_param.S=1;break;case'n':g_param.n=1;break;case'i':g_param.i=1;break;case'd':g_param.d=1;break;case'?':// printf("unknownparam:%s\n",optarg);return-2;default:printf("??getoptreturnedcharactercode%d\n",c);return-3;}}/*校验只能用一种排序方式*/{int total=if(g_param.c==1)++total;if(g_param.t==1)++total;if(g_param.u==1)++total;if(g_param.S==1)++total;if(g_param.n==1)++total;g_com_func=cmp_filename; /*先置为默认排序方式 以文件名排序if(total>1){printf("theparamsortparamerror,nowsortbyfilename\n");}elseif(total==1) /*仅在此情况下,才有可能排序方式要变*/{if(g_param.c)g_com_func=cmp_last_statetime; /*以最后状态修改时间排序*/elseif(g_param.t)g_com_func=cmp_last_change; /*以文件最后修改时间排序elseif(g_param.u)g_com_func=cmp_last_accesstime;以文件最后访问时间排序*/elseif(g_param.S)g_com_func=cmp_filesize; /*以文件大小排序 */}}/*if(optind<argc)//optind储存第一个不包含选项的命令行参数{structstat statbuf;//#include<sys/stat.h>中while(optind<argc){if(lstat(argv[optind],&statbuf)<0)//intlstat(constchar*path,structstat*buf);path:文件路径名buf:保存文件信息的结构体,成功执行返回0,失败返回-1{printf("lstatfile'%s'error:%s\n",argv[optind++],strerror(errno));exit(-1);}if(S_ISDIR(statbuf.st_mode))//是否为目录add_dir(argv[optind++],&g_dir_head);//添加目录elseif(S_ISLNK(statbuf.st_mode))//是否为符号链接{char dst_name[MAX_PATH]={0};if(readlink(argv[optind],dst_name,MAX_PATH-1)<0)//#include<unistd.h>,intreadlink(const char*path, char*buf,size_t bufsiz);continue;save_file_info(&g_dir_info,&statbuf,argv[optind++],dst_name);}else{save_file_info(&g_dir_info,&statbuf,argv[optind++],NULL);}}}else{add_dir("./",&g_dir_head);/*如果不带文件,则默认为当前目录*/}return0;}/*初始化*/staticvoidinit(){memset(&g_dir_info,0,sizeof(structdir_info));//memset可以方便的清空一个结构类型的变量memset(&g_param,0,sizeof(structparam));INIT_LIST_HEAD(&g_dir_head);}/*打印文件的详细信息*/staticvoid_print_detail(structfile_info*info){int n;char timebuf[128]={0};structpasswd *ppasswd=NULL; /*跟用户相*/structgroup *pgroup=NULL; /*跟用户组相/*打印i节点号*/if(g_param.i&&g_param.l)printf("%-10d",(int)(info->statbuf.st_ino));/*st_mode:1、S_IFMT0170000文件类型的位遮罩2、S_IFSOCK0140000scoket3、S_IFLNK0120000符号连接4、S_IFREG0100000一般文件5、S_IFBLK0060000区块装置6、S_IFDIR0040000目录7、S_IFCHR0020000字符装置8、S_IFIFO0010000先进先出9、S_ISUID04000文件的(setuser-idonexecution)位10、S_ISGID02000文件的(setgroup-idonexecution)位11、S_ISVTX01000文件的sticky位12、S_IRUSR(S_IREAD)00400文件所有者具可读取权限13、S_IWUSR(S_IWRITE)00200文件所有者具可写入权限14、S_IXUSR(S_IEXEC)00100文件所有者具可执行权限15、S_IRGRP00040用户组具可读取权限 u:r16、S_IWGRP00020用户组具可写入权限 u:w17、S_IXGRP00010用户组具可执行权限 u:x18、S_IROTH00004其他用户具可读取权限 o:r19、S_IWOTH00002其他用户具可写入权限 o:w20、S_IXOTH00001其他用户具可执行权限上述的文件类型在 POSIX中定义了检查这些类型的宏定o:x21、S_ISLNK(st_mode)判断是否为符号连接22、S_ISREG(st_mode)是否为一般文件23、S_ISDIR(st_mode)是否为目录24、S_ISCHR(st_mode)是否为字符装置文件25、S_ISBLK(s3e)是否为先进先出26S_ISSOCK(st_mode)是否为socket若一目录具有sticky位(S_ISVTX),则表示在此目录下的文件只root来删除或改名.*//*打印文件类型*/putchar('-');elseif(S_ISDIR(info->statbuf.st_mode))putchar('d');elseif(S_ISCHR(info->statbuf.st_mode))putchar('c');elseif(S_ISBLK(info->statbuf.st_mode))putchar('b');elseif(S_ISFIFO(info->statbuf.st_mode))putchar('f');elseif(S_ISLNK(info->statbuf.st_mode))putchar('l');elseif(S_ISSOCK(info->statbuf.st_mode))putchar('s');elseputchar('?');/*移位的方法比通过宏操作,代码要简洁些*/for(n=8;n>=0;--n){if(info->statbuf.st_mode&(1<<n)){switch(n%3){case2:putchar('r');break;case1:putchar('w');break;case0:putchar('x');break;}}elseputchar('-');}putchar('');/*打印硬连接数*/printf("%-2d",(int)(info->statbuf.st_nlink));/*打印用户ID*/if((ppasswd=getpwuid(info->statbuf.st_uid))!=NULL)printf("%-13.13s",ppasswd->pw_name);elseprintf("%-5d",info->statbuf.st_uid);/*打印用户组ID*/if((pgroup=getgrgid(info->statbuf.st_gid))!=NULL)printf("%-13.13s",pgroup->gr_name);elseprintf("%-5d",info->statbuf.st_gid);/*打印文件大小*/if(g_param.h==1)printf("%5.1fk",(double)((info->statbuf.st_size)/1024.0));elseprintf("%-6d",(int)(info->statbuf.st_size));/*按需打印块大小*/if(g_param.d)printf("%-6d",(int)(info->statbuf.st_blksize));/*打印时间*/ctime_r(&(info->statbuf.st_mtime),timebuf);//等价于asctime_r(localtime(timer),buf)if(timebuf[0]!=0)timebuf[strlen(timebuf)-1]=0;/*去掉'\n'*/printf("%-20.20s",timebuf);/*打印文件名*/printf("%s",info->fil_name);if(info->is_link&&(g_para

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论