#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #define OK 1 #define ERROR 0 #define STACK_INIT_SIZE 100 // 存储空间初始分配量 #define STACKINCREMENT 10 // 存储空间分配增量 #define MAXTIME 9999//MAXTIME用来表示该两个站点之间不互相连通 typedef struct stop /*定义结构体*/ { char stopname[100];//站名 int stopnumber;//站号 struct stop *next; } stop,*stop1; typedef struct lineway { char linenumber[10];;//线路号 int stopcount;//该线路上站的个数 stop station[30]; } way; struct total { int totalline;//线路总数 way line[20];//线路 }; typedef int SElemType; // 定义栈元素类型 typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等 typedef int PathMatrix; typedef int DistancMatrix ; typedef struct vex { int num;//存储站点的序号,用于arc[][] char name[30];//存储站名 } mvex; typedef struct { int vexnum;//vexnum表示顶点个数, int arcnum;//arcnum表示弧的个数 int **arc;//arc存放该结构体的二维数组,定义成指针是为了后续的动态分配,存放弧的信息。该二维数组存放通过两个点之间所需要的时间 mvex *vex;//存放顶点信息 } Mgraph; struct SqStack { SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL SElemType *top; // 栈顶指针 int stacksize; // 当前已分配的存储空间,以元素为单位 }; // 顺序栈 Status InitStack(SqStack &S) { // 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!S.base) return ERROR; S.top=S.base; S.stacksize=STACK_INIT_SIZE; return OK; } Status Push(SqStack &S,SElemType e) { // 在栈S中插入元素e为新的栈顶元素 if(S.top-S.base>=S.stacksize) { S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType)); if(!S.base) return ERROR; S.top=S.base+S.stacksize; S.stacksize+=STACKINCREMENT; } *S.top++=e; return OK; } Status Pop(SqStack &S,SElemType &e) { // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR if(S.top==S.base) return ERROR; e=*--S.top; return OK; } Status GetTop(SqStack S,SElemType &e) { // 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR if(S.top==S.base) return ERROR; e=*(S.top-1); return OK; } int StackLength(SqStack S) { // 返回栈S的元素个数 int i; i=S.top-S.base; return i; } Status StackTraverse(SqStack S) { // 从栈顶到栈底依次输出栈中的每个元素 SElemType *p = (SElemType *)malloc(sizeof(SElemType)); p = S.top; if(S.top==S.base)printf("The Stack is Empty!"); else { printf("The Stack is: "); p--; while(p>=S.base) { printf("%d ", *p); p--; } } printf("\n"); return OK; } void search(struct total&ex)//查询线路 { char x[10]; int i,j,index; printf("请输入您要查询的线路\n"); scanf("%s",x); for(i=0; i<ex.totalline; i++) { if(strcmp(ex.line[i].linenumber,x)==0) { index=i; break; } } for(j=0; j<ex.line[index].stopcount; j++) { printf("%s ",ex.line[index].station[j].stopname); } printf("\n"); printf("按任意键返回主菜单\n"); system("pause"); } int checkname(char *s,Mgraph C)//判断是否存在该站点 { int i; for(i=0;i<C.vexnum;i++) if(strcmp(s,C.vex[i].name)==0) return 1; return 0; } void searchname(struct total&ex,Mgraph C)//按站点名称查询线路 { char x[20]; int i,j; int count=0;//存储找到的线路的个数 while(1) { printf("请输入您要查询的站点名称\n"); scanf("%s",x); if(checkname(x,C)==0) printf("该站点不存在,请重新输入"); else break; } for(i=0; i<ex.totalline; i++) { for(j=0; j<ex.line[i].stopcount; j++) { if(strcmp(ex.line[i].station[j].stopname,x)==0) { printf("%s\n",ex.line[i].linenumber); count++; } } if(j<ex.line[i].stopcount) break; } if(count==0) printf("没有找到您输入的站点\n"); } int getnumByname(char name[30],Mgraph C)//通过站名来查找站的编号 { int i; for(i=0;i<C.vexnum;i++) if(strcmp(name,C.vex[i].name)==0) return C.vex[i].num; return 0; } char* getnameBynum(int num,Mgraph C)//通过站号来查站名 { int i; for(i=0;i<C.vexnum;i++) if(num==C.vex[i].num) return C.vex[i].name; return NULL; } void ShortestPath_FLOYD(Mgraph G, int**P, int**D)//D是dist,P用来存储路径,P[i][j]存储j的前驱 { // 算法7.16 // 用Floyd算法求有向网G中各对顶点v和w之间的最短路径 int v,w,u; for (v=1; v<=G.vexnum; ++v) // 各对结点之间初始已知路径及距离 for (w=1; w<=G.vexnum; ++w)//初始化P数组 { D[v][w] = G.arc[v][w]; if(v!=w&&D[v][w]!=MAXTIME) P[v][w]=v; else P[v][w]=-1; }//for for (u=1; u<=G.vexnum; ++u) for (v=1; v<=G.vexnum; ++v) for (w=1; w<=G.vexnum; ++w) if (D[v][u]+D[u][w] < D[v][w]) // 从v经u到w的一条路径更短 { D[v][w] = D[v][u]+D[u][w]; P[v][w]=P[u][w]; }//if } // ShortestPath_FLOYD*/ void exchange(int**P,Mgraph C) { char s1[30],s2[30];//用来存储读取arc文件中的两个有关系的站名 char *s; int m=0,n=0,e=-1,i,j; while(1) { printf("请输入起始站\n"); scanf("%s",s1); if(checkname(s1,C)==0) printf("该站点不存在,请重新输入"); else break; } while(1) { printf("请输入终点站\n"); scanf("%s",s2); if(checkname(s2,C)==0) printf("该站点不存在,请重新输入"); else break; } m=getnumByname(s1,C); n=getnumByname(s2,C); SqStack S; InitStack(S); if(P[m][n]!=-1) Push(S,n); i=m; j=n; while(1) { e=P[i][j]; Push(S,e); if(e==i) break; j=e;} StackTraverse(S); SElemType *p = (SElemType *)malloc(sizeof(SElemType)); p = S.top; if(S.top==S.base)printf("The Stack is Empty!"); else { printf("The Stack is: "); p--; while(p>=S.base) { s=getnameBynum(*p,C); printf("%s-",s); // printf("%d", *p); p--; } } printf("\n"); }
static void recfield (LexState *ls, struct ConsControl *cc) { /* recfield -> (NAME | `['exp1`]') = exp1 */ FuncState *fs = GetCurrentFuncState( ls ); int reg = fs->freereg; expdesc key, val; if (ls->t.token == TK_NAME) { luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); } else /* ls->t.token == '[' */ { yindex(ls, &key); } cc->nh++; checknext(ls, '='); int rkkey = luaK_exp2RK(fs, &key); expr(ls, &val); luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); fs->freereg = reg; /* free registers */ }
static void primaryexp (LexState *ls, expdesc *v) { /* primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ FuncState *fs = ls->fs; prefixexp(ls, v); for (;;) { switch (ls->t.token) { case '.': { /* field */ field(ls, v); break; } case '[': { /* `[' exp1 `]' */ expdesc key; luaK_exp2anyreg(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; } case ':': { /* `:' NAME funcargs */ expdesc key; luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); funcargs(ls, v); break; } case '(': case TK_STRING: case '{': { /* funcargs */ luaK_exp2nextreg(fs, v); funcargs(ls, v); break; } default: return; } } }
void searchname(struct total&ex,Mgraph C)//按站点名称查询线路 { char x[20]; int i,j; int count=0;//存储找到的线路的个数 while(1) { printf("请输入您要查询的站点名称\n"); scanf("%s",x); if(checkname(x,C)==0) printf("该站点不存在,请重新输入"); else break; } for(i=0; i<ex.totalline; i++) { for(j=0; j<ex.line[i].stopcount; j++) { if(strcmp(ex.line[i].station[j].stopname,x)==0) { printf("%s\n",ex.line[i].linenumber); count++; } } if(j<ex.line[i].stopcount) break; } if(count==0) printf("没有找到您输入的站点\n"); }
static void field (LexState *ls, expdesc *v) { /* field -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; expdesc key; luaK_exp2anyreg(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); luaK_indexed(fs, v, &key); }
/* * open input file * Input : char* p * Output : int error code * * Try to open the file whose filename is p, return YES if opened, else NO * Updates fname with the actual opened name * input is the handle of the opened file * */ int openin (char *p) { strcpy(fname, p); strcpy(fname_copy, fname); fixname (fname); if (!checkname (fname)) return (NO); if ((input = fopen (fname, "r")) == NULL) { pl ("Open failure\n"); return (NO); } kill_line (); return (YES); }
int umountall(char **typelist) { struct xvfsconf vfc; struct fstab *fs; int rval; char *cp; static int firstcall = 1; if ((fs = getfsent()) != NULL) firstcall = 0; else if (firstcall) errx(1, "fstab reading failure"); else return (0); do { /* Ignore the root. */ if (strcmp(fs->fs_file, "/") == 0) continue; /* * !!! * Historic practice: ignore unknown FSTAB_* fields. */ if (strcmp(fs->fs_type, FSTAB_RW) && strcmp(fs->fs_type, FSTAB_RO) && strcmp(fs->fs_type, FSTAB_RQ)) continue; /* Ignore unknown file system types. */ if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) continue; if (checkvfsname(fs->fs_vfstype, typelist)) continue; /* * We want to unmount the file systems in the reverse order * that they were mounted. So, we save off the file name * in some allocated memory, and then call recursively. */ if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL) err(1, "malloc failed"); (void)strcpy(cp, fs->fs_file); rval = umountall(typelist); rval = checkname(cp, typelist) || rval; free(cp); return (rval); } while ((fs = getfsent()) != NULL); return (0); }
int remove_file(struct inode *dir, const char *name){ /*判断目录是否有效*/ if(dir->ext2_inode.i_block[0] != UINT_MAX){ perror("inode_operations.c: remove_file error! current dir is a file!\n"); return -1; } /*判断名字是否有效*/ if(checkname(name) == -1){ perror("inode_operations.c: remove_file error! filename is illegal!\n"); return -1; } char buf[BLOCK_SIZE]; struct ext2_dir_entry_2 *pentry; int dir_datablocks = dir->ext2_inode.i_blocks;/*数据块个数*/ int i = 1; int j = 0; int num = BLOCK_SIZE/sizeof(struct ext2_dir_entry_2); while(i <= dir_datablocks){ /*取出目录节点中第i块逻辑块所在的物理块的数据,放入buf*/ get_block_data(dir->ext2_inode.i_block[i],buf); pentry = (struct ext2_dir_entry_2 *)buf; //printf("inode_operations.c: check : dir_datablocks: %d\n",i); /*比较每一项*/ while(j<num){ //printf("inode_operations.c: check : entry: %d\n",j); /*比较pentry->inode不为0的每一项*/ if(pentry->inode && !strcmp(pentry->name,name)){ if(free_inode(pentry->inode) == -1){ perror("节点释放失败!\n"); return -1; }; /*清空该目录项*/ memset(pentry,'\0',sizeof(struct ext2_dir_entry_2)); /*写回磁盘,更新数据*/ write_block_data(dir->ext2_inode.i_block[i],buf); return 1; } j++; pentry++; } i++; } printf("no such file,please check your filename!\n"); return -1; }
void checkbase(Student *stu) //根据条件查询 { int type; do { printf("\n请输入序号选择相应功能\n"); printf("******** 1.按学号查询 ********\n"); printf("******** 2.按姓名查询 ********\n"); printf("******** 3.按名次查询 ********\n"); printf("******** 0.退出 ********\n"); scanf("%d",&type); switch(type) { case 0:printf("");break; case 1:checknum(stu);break; case 2:checkname(stu);break; case 3:checkrank(stu);break; default:printf("没有该选项,请重输");break; } }while(type!=0); }
int expression() { //printf("begin to do expression\n"); kope=0; knum=0; typ=2; char exp[80]=""; int expj=0; ifexpression=0; gets(exp); /*ÐèҪɾ³ý*/integer=1; do{ printf("now string=%s\n",string); printf("now number=%d\n",integer); printf("now type=%d\n",typ); //len=strlen(string); if (typ==2) { knum++; num[knum]=integer; } if (typ==1) { //printf("find a operater\n"); if ((string[0]==')')) { doexpression(); } else { kope++; operater[kope]=string[0]; } } if (exp[expj]==0) break; if ((exp[expj]=='+')||(exp[expj]=='-')||(exp[expj]=='*')||(exp[expj]=='/')||(exp[expj]='(')||(exp[expj]=')')) { //printf("findstring\n"); string[0]=exp[expj]; string[1]='\0'; //printf("finish\n"); do{ expj++; }while (exp[expj]==' '); typ=1; } else if (exp[expj]=':') { //printf("find :\n"); memset(string,0,80); int i=0; while ((exp[expj]!=' ')&&(exp[expj]!=0)) { string[i]=exp[expj]; expj++; } int ctf=checkname(1,string); if (ctf==0) { return 0; } int x=findidentifier(string); if (x==0) { printf("error:this word is not defined!\n"); return 0; } if (identifier.type[x]==1) { printf("string can't be calculated in a expression!\n"); return 0; } integer=identifier.intvalue[x]; while (exp[expj]==' ') { expj++; } }else { printf("find digit\n"); integer=0; while ((exp[expj]>='0')&&(exp[expj]<='9')) { integer=integer*10+exp[expj]-'0'; expj++; } typ=2; while (exp[expj]==' ') { expj++; } } printf("finish\n"); }while (1); ifre=1; doexpression(); return 2; }
static void primaryexp (LexState *ls, expdesc *v) { /* primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ FuncState *fs = ls->fs; prefixexp(ls, v); for (;;) { switch (ls->t.token) { case '.': { /* field */ field(ls, v); break; } case '[': { /* `[' exp1 `]' */ expdesc key; luaK_exp2anyreg(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; } case ':': { /* `:' NAME funcargs */ expdesc key; luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); funcargs(ls, v); break; } #if LUA_WIDESTRING case '(': case TK_STRING: case TK_WSTRING: case '{': { /* funcargs */ #else case '(': case TK_STRING: case '{': { /* funcargs */ #endif /* LUA_WIDESTRING */ luaK_exp2nextreg(fs, v); funcargs(ls, v); break; } default: return; } } } static void simpleexp (LexState *ls, expdesc *v) { #if LUA_WIDESTRING /* simpleexp -> NUMBER | STRING | WSTRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp */ #else /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp */ #endif /* LUA_WIDESTRING */ switch (ls->t.token) { case TK_NUMBER: { init_exp(v, VKNUM, 0); v->u.nval = ls->t.seminfo.r; break; } case TK_STRING: { codestring(ls, v, ls->t.seminfo.ts); break; } #if LUA_WIDESTRING case TK_WSTRING: { codewstring(ls, v, ls->t.seminfo.ts); break; } #endif /* LUA_WIDESTRING */ case TK_NIL: { init_exp(v, VNIL, 0); break; } case TK_TRUE: { init_exp(v, VTRUE, 0); break; } case TK_FALSE: { init_exp(v, VFALSE, 0); break; } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, "cannot use " LUA_QL("...") " outside a vararg function"); fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; } case '{': { /* constructor */ constructor(ls, v); return; } case TK_FUNCTION: { luaX_next(ls); body(ls, v, 0, ls->linenumber); return; } default: { primaryexp(ls, v); return; } } luaX_next(ls); } static UnOpr getunopr (int op) { switch (op) { case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; case '#': return OPR_LEN; default: return OPR_NOUNOPR; } } static BinOpr getbinopr (int op) { switch (op) { case '+': return OPR_ADD; case '-': return OPR_SUB; case '*': return OPR_MUL; case '/': return OPR_DIV; case '%': return OPR_MOD; #if LUA_BITFIELD_OPS case '&': return OPR_BAND; case '|': return OPR_BOR; case TK_XOR: return OPR_BXOR; case TK_SHL: return OPR_BSHL; case TK_SHR: return OPR_BSHR; #endif /* LUA_BITFIELD_OPS */ case '^': return OPR_POW; case TK_CONCAT: return OPR_CONCAT; case TK_NE: return OPR_NE; case TK_EQ: return OPR_EQ; case '<': return OPR_LT; case TK_LE: return OPR_LE; case '>': return OPR_GT; case TK_GE: return OPR_GE; case TK_AND: return OPR_AND; case TK_OR: return OPR_OR; default: return OPR_NOBINOPR; } } static const struct { lu_byte left; /* left priority for each binary operator */ lu_byte right; /* right priority */ } priority[] = { /* ORDER OPR */ #if LUA_BITFIELD_OPS {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, /* bitwise operators */ #endif /* LUA_BITFIELD_OPS */ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ {10, 9}, {5, 4}, /* power and concat (right associative) */ {3, 3}, {3, 3}, /* equality and inequality */ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ {2, 2}, {1, 1} /* logical (and/or) */ }; #define UNARY_PRIORITY 8 /* priority for unary operators */ /* ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ** where `binop' is any binary operator with a priority higher than `limit' */ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { BinOpr op; UnOpr uop; enterlevel(ls); uop = getunopr(ls->t.token); if (uop != OPR_NOUNOPR) { luaX_next(ls); subexpr(ls, v, UNARY_PRIORITY); luaK_prefix(ls->fs, uop, v); } else simpleexp(ls, v); /* expand while operators have priorities higher than `limit' */ op = getbinopr(ls->t.token); while (op != OPR_NOBINOPR && priority[op].left > limit) { expdesc v2; BinOpr nextop; luaX_next(ls); luaK_infix(ls->fs, op, v); /* read sub-expression with higher priority */ nextop = subexpr(ls, &v2, priority[op].right); luaK_posfix(ls->fs, op, v, &v2); op = nextop; } leavelevel(ls); return op; /* return first untreated operator */ }
int main(int argc, char *argv[]) { int all, errs, ch, mntsize, error; char **typelist = NULL; struct statfs *mntbuf, *sfs; struct addrinfo hints; all = errs = 0; while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1) switch (ch) { case 'A': all = 2; break; case 'a': all = 1; break; case 'F': setfstab(optarg); break; case 'f': fflag = MNT_FORCE; break; case 'h': /* -h implies -A. */ all = 2; nfshost = optarg; break; case 't': if (typelist != NULL) err(1, "only one -t option may be specified"); typelist = makevfslist(optarg); break; case 'v': vflag = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; /* Start disks transferring immediately. */ if ((fflag & MNT_FORCE) == 0) sync(); if ((argc == 0 && !all) || (argc != 0 && all)) usage(); /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); if (nfshost != NULL) { memset(&hints, 0, sizeof hints); error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); if (error) errx(1, "%s: %s", nfshost, gai_strerror(error)); } switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) break; /* * We unmount the nfs-mounts in the reverse order * that they were mounted. */ for (errs = 0, mntsize--; mntsize > 0; mntsize--) { sfs = &mntbuf[mntsize]; if (checkvfsname(sfs->f_fstypename, typelist)) continue; if (strcmp(sfs->f_mntonname, "/dev") == 0) continue; if (umountfs(sfs) != 0) errs = 1; } free(mntbuf); break; case 1: if (setfsent() == 0) err(1, "%s", getfstab()); errs = umountall(typelist); break; case 0: for (errs = 0; *argv != NULL; ++argv) if (checkname(*argv, typelist) != 0) errs = 1; break; } exit(errs); }
int create(struct inode *dir, const char *name, int len, int mode, struct inode ** res_inode){ /*判断目录是否有效*/ if(dir->ext2_inode.i_block[0] != UINT_MAX){ perror("inode_operations.c: create error! dir is a file!\n"); return -1; } /*判断名字是否有效*/ if(checkname(name) == -1){ perror("inode_operations.c: create error! filename is illegal!\n"); return -1; } /*判断是否已存在*/ if(is_exist(dir,name) == 1){ perror("inode_operations.c: create error! file is alreay exists!\n"); return -1; } char buf[BLOCK_SIZE]; struct ext2_dir_entry_2 *pentry; int dir_datablocks = dir->ext2_inode.i_blocks;/*数据块个数*/ int i = 1; int num = BLOCK_SIZE/sizeof(struct ext2_dir_entry_2); while(i <= dir_datablocks){ /*取出目录节点中第i块逻辑块所在的物理块的数据,放入buf*/ get_block_data(dir->ext2_inode.i_block[i],buf); pentry = (struct ext2_dir_entry_2 *)buf; /*寻找pentry->inode为0的每一项,表示未使用,填写目录项*/ //printf("inode_operations.c: create : dir_datablocks: %d\n",i); int j = 0; while(j<num){ //printf("inode_operations.c: create : entry: %d\n",j); if(!pentry->inode){ pentry->name_len = len; strcpy(pentry->name,name); pentry->file_type = mode; pentry->rec_len = 8 + len; pentry->inode = new_inode(); write_block_data(dir->ext2_inode.i_block[i],buf);//更新该数据块 *res_inode=(struct inode *)malloc(sizeof(struct inode)); if(*res_inode != NULL){ get_inode_data(pentry->inode,*res_inode); return 1; } } j++; pentry++; } i++; } /*数据块表项已满,则需申请新的数据块来存放新的目录项*/ if(dir_datablocks>=14){ perror("inode_operations.c create error! dir_entry is full,no more sub_dir!\n"); return -1; } dir_datablocks = ++(dir->ext2_inode.i_blocks); dir->ext2_inode.i_block[dir_datablocks] = new_block(); write_inode_data(dir->i_number,dir);//因为申请了新块,inode节点及时更新 get_block_data(dir->ext2_inode.i_block[dir_datablocks],buf); pentry = (struct ext2_dir_entry_2 *)buf; pentry->name_len = len; strcpy(pentry->name,name); pentry->file_type = mode; pentry->rec_len = 8 + len; pentry->inode = new_inode(); write_block_data(dir->ext2_inode.i_block[dir_datablocks],buf);//更新该数据块 if((*res_inode=(struct inode *)malloc(sizeof(struct inode))) != NULL){ get_inode_data(pentry->inode,*res_inode); return 1; } return -1; }
int main(int argc, char *argv[]) { int all, errs, ch, mntsize, error, nfsforce, ret; char **typelist = NULL; struct statfs *mntbuf, *sfs; struct addrinfo hints; nfsforce = all = errs = 0; while ((ch = getopt(argc, argv, "AaF:fh:Nnt:v")) != -1) switch (ch) { case 'A': all = 2; break; case 'a': all = 1; break; case 'F': setfstab(optarg); break; case 'f': fflag |= MNT_FORCE; break; case 'h': /* -h implies -A. */ all = 2; nfshost = optarg; break; case 'N': nfsforce = 1; break; case 'n': fflag |= MNT_NONBUSY; break; case 't': if (typelist != NULL) err(1, "only one -t option may be specified"); typelist = makevfslist(optarg); break; case 'v': vflag = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if ((fflag & MNT_FORCE) != 0 && (fflag & MNT_NONBUSY) != 0) err(1, "-f and -n are mutually exclusive"); /* Start disks transferring immediately. */ if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0 && nfsforce == 0) sync(); if ((argc == 0 && !all) || (argc != 0 && all)) usage(); if (nfsforce != 0 && (argc == 0 || nfshost != NULL || typelist != NULL)) usage(); /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); if (nfshost != NULL) { memset(&hints, 0, sizeof hints); error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); if (error) errx(1, "%s: %s", nfshost, gai_strerror(error)); } switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) break; /* * We unmount the nfs-mounts in the reverse order * that they were mounted. */ for (errs = 0, mntsize--; mntsize > 0; mntsize--) { sfs = &mntbuf[mntsize]; if (checkvfsname(sfs->f_fstypename, typelist)) continue; if (strcmp(sfs->f_mntonname, "/dev") == 0) continue; if (umountfs(sfs) != 0) errs = 1; } free(mntbuf); break; case 1: if (setfsent() == 0) err(1, "%s", getfstab()); errs = umountall(typelist); break; case 0: for (errs = 0; *argv != NULL; ++argv) if (nfsforce != 0) { /* * First do the nfssvc() syscall to shut down * the mount point and then do the forced * dismount. */ ret = nfssvc(NFSSVC_FORCEDISM, *argv); if (ret >= 0) ret = unmount(*argv, MNT_FORCE); if (ret < 0) { warn("%s", *argv); errs = 1; } } else if (checkname(*argv, typelist) != 0) errs = 1; break; } exit(errs); }
void f_create(Chan *cp, Oldfcall *in, Oldfcall *ou) { Iobuf *p, *p1; Dentry *d, *d1; File *f; int slot, slot1, fmod; int32_t addr, addr1, path; Qid qid; Tlock *t; Wpath *w; if(CHAT(cp)) { print("c_create %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" name = %s\n", in->name); print(" perm = %lx+%lo\n", (in->perm>>28)&0xf, in->perm&0777); print(" mode = %d\n", in->mode); } p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { ou->err = Eronly; goto out; } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; if(!(d->mode & DDIR)) { ou->err = Edir2; goto out; } if(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) { ou->err = Eaccess; goto out; } accessdir(p, d, FREAD); if(!strncmp(in->name, ".", sizeof(in->name)) || !strncmp(in->name, "..", sizeof(in->name))) { ou->err = Edot; goto out; } if(checkname(in->name)) { ou->err = Ename; goto out; } addr1 = 0; slot1 = 0; /* set */ for(addr=0;; addr++) { p1 = dnodebuf(p, d, addr, 0); if(!p1) { if(addr1) break; p1 = dnodebuf(p, d, addr, Tdir); } if(p1 == 0) { ou->err = Efull; goto out; } if(checktag(p1, Tdir, d->qid.path)) { putbuf(p1); goto phase; } for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) { if(!addr1) { addr1 = p1->addr; slot1 = slot + addr*DIRPERBUF; } continue; } if(!strncmp(in->name, d1->name, sizeof(in->name))) { putbuf(p1); ou->err = Eexist; goto out; } } putbuf(p1); } switch(in->mode & 7) { case MEXEC: case MREAD: /* seems only useful to make directories */ fmod = FREAD; break; case MWRITE: fmod = FWRITE; break; case MBOTH: fmod = FREAD+FWRITE; break; default: ou->err = Emode; goto out; } if(in->perm & PDIR) if((in->mode & MTRUNC) || (in->perm & PAPND) || (fmod & FWRITE)) goto badaccess; /* * do it */ path = qidpathgen(&f->fs->dev); p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod); d1 = getdir(p1, slot1); if(!d1 || checktag(p1, Tdir, d->qid.path)) { if(p1) putbuf(p1); goto phase; } if(d1->mode & DALLOC) { putbuf(p1); goto phase; } strncpy(d1->name, in->name, sizeof(in->name)); /* * bogus argument passing -- see console.c */ if(cp == cons.chan) { d1->uid = cons.uid; d1->gid = cons.gid; } else { d1->uid = f->uid; d1->gid = d->gid; in->perm &= d->mode | ~0666; if(in->perm & PDIR) in->perm &= d->mode | ~0777; } d1->qid.path = path; d1->qid.version = 0; d1->mode = DALLOC | (in->perm & 0777); if(in->perm & PDIR) { d1->mode |= DDIR; d1->qid.path |= QPDIR; } if(in->perm & PAPND) d1->mode |= DAPND; t = 0; if(in->perm & PLOCK) { d1->mode |= DLOCK; t = tlocked(p1, d1); } accessdir(p1, d1, FWRITE); mkqid(&qid, d1, 0); putbuf(p1); accessdir(p, d, FWRITE); /* * do a walk to new directory entry */ w = newwp(); if(!w) { ou->err = Ewalk; goto out; } w->addr = f->addr; w->slot = f->slot; w->up = f->wpath; f->wpath = w; f->qid = qid; f->tlock = t; f->lastra = 0; if(in->mode & MRCLOSE) fmod |= FREMOV; f->open = fmod; f->addr = addr1; f->slot = slot1; if(t) t->file = f; mkqid9p1(&ou->qid, &qid); goto out; badaccess: ou->err = Eaccess; goto out; phase: ou->err = Ephase; out: if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid; }
void f_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou) { Iobuf *p, *p1; Dentry *d, *d1, xd; File *f; int slot; int32_t addr; if(CHAT(cp)) { print("c_wstat %d\n", cp->chan); print(" fid = %d\n", in->fid); } p = 0; p1 = 0; d1 = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { ou->err = Eronly; goto out; } /* * first get parent */ if(f->wpath) { p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); d1 = getdir(p1, f->wpath->slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { ou->err = Ephase; goto out; } } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; convM2D9p1(in->stat, &xd); if(CHAT(cp)) { print(" d.name = %s\n", xd.name); print(" d.uid = %d\n", xd.uid); print(" d.gid = %d\n", xd.gid); print(" d.mode = %.4x\n", xd.mode); } /* * if chown, * must be god */ while(xd.uid != d->uid) { if(wstatallow) /* set to allow chown during boot */ break; ou->err = Enotu; goto out; } /* * if chgroup, * must be either * a) owner and in new group * b) leader of both groups */ while(xd.gid != d->gid) { if(wstatallow || writeallow) /* set to allow chgrp during boot */ break; if(d->uid == f->uid && ingroup(f->uid, xd.gid)) break; if(leadgroup(f->uid, xd.gid)) if(leadgroup(f->uid, d->gid)) break; ou->err = Enotg; goto out; } /* * if rename, * must have write permission in parent */ if(xd.name[0] == 0) strncpy(xd.name, d->name, sizeof(xd.name)); while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) { if(checkname(xd.name)) { ou->err = Ename; goto out; } if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) { ou->err = Ename; goto out; } /* * drop entry to prevent lock, then * check that destination name is unique, */ putbuf(p); for(addr=0;; addr++) { p = dnodebuf(p1, d1, addr, 0); if(!p) break; if(checktag(p, Tdir, d1->qid.path)) { putbuf(p); continue; } for(slot=0; slot<DIRPERBUF; slot++) { d = getdir(p, slot); if(!(d->mode & DALLOC)) continue; if(!strncmp(xd.name, d->name, sizeof(xd.name))) { ou->err = Eexist; goto out; } } putbuf(p); } /* * reacquire entry */ p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ephase; goto out; } if(wstatallow || writeallow) /* set to allow rename during boot */ break; if(!d1 || iaccess(f, d1, DWRITE)) { ou->err = Eaccess; goto out; } break; } /* * if mode/time, either * a) owner * b) leader of either group */ while(d->mtime != xd.mtime || ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) { if(wstatallow) /* set to allow chmod during boot */ break; if(d->uid == f->uid) break; if(leadgroup(f->uid, xd.gid)) break; if(leadgroup(f->uid, d->gid)) break; ou->err = Enotu; goto out; } d->mtime = xd.mtime; d->uid = xd.uid; d->gid = xd.gid; d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR)); strncpy(d->name, xd.name, sizeof(d->name)); if(wstatallow) { p->flags |= Bmod; if(xd.atime) d->atime = xd.atime; if(xd.mtime) d->mtime = xd.mtime; } else accessdir(p, d, FWSTAT); out: if(p) putbuf(p); if(p1) putbuf(p1); if(f) qunlock(f); ou->fid = in->fid; }
int mkdir(struct inode *dir, const char *name, int len, int mode){ /*判断目录是否有效*/ if(dir->ext2_inode.i_block[0] != UINT_MAX){ perror("inode_operations.c: mkdir error! dir is a file!\n"); return -1; } /*判断名字是否有效*/ if(checkname(name) == -1){ perror("inode_operations.c: mkdir error! dirname is illegal!\n"); return -1; } /*判断是否已存在*/ if(is_exist(dir,name) == 1){ perror("inode_operations.c: mkdir error! dirname is alreay exists!\n"); return -1; } char buf[BLOCK_SIZE]; struct inode *m_inode; struct ext2_dir_entry_2 *pentry; int dir_datablocks = dir->ext2_inode.i_blocks;/*数据块个数*/ int i = 1; int num = BLOCK_SIZE/sizeof(struct ext2_dir_entry_2); while(i <= dir_datablocks){ /*取出目录节点中第i块逻辑块所在的物理块的数据,放入buf*/ get_block_data(dir->ext2_inode.i_block[i],buf); pentry = (struct ext2_dir_entry_2 *)buf; /*寻找pentry->inode为0的每一项,表示未使用*/ int j = 0; while(j<num){ if(!pentry->inode){ pentry->name_len = len; strcpy(pentry->name,name); pentry->file_type = mode; pentry->rec_len = 8 + len; pentry->inode = new_inode(); write_block_data(dir->ext2_inode.i_block[i],buf);//更新该数据块 /*下面更新为目录项(文件夹)申请的inode节点信息,并为其预分配一块数据块,用于存放子目录或文件*/ if((m_inode=(struct inode*)malloc(sizeof(struct inode))) != NULL){ get_inode_data(pentry->inode,m_inode); m_inode->ext2_inode.i_block[0] = UINT_MAX;//表示该节点是目录节点 m_inode->ext2_inode.i_block[1] = new_block();//为每个目录节点预分配一块数据块,存放目录项 m_inode->ext2_inode.i_blocks = 1; write_inode_data(pentry->inode,m_inode); free(m_inode); return 1; } } j++; pentry++; } i++; } /*数据块表项已满,则需申请新的数据块来存放新的目录项*/ if(dir_datablocks>=14){ perror("inode_operations.c mkdir error! dir_entry is full,no more sub_dir!\n"); return -1; } dir_datablocks = ++dir->ext2_inode.i_blocks; dir->ext2_inode.i_block[dir_datablocks] = new_block(); write_inode_data(dir->i_number,dir);//因为申请了新块,inode节点及时更新 get_block_data(dir->ext2_inode.i_block[dir_datablocks],buf); pentry = (struct ext2_dir_entry_2 *)buf; pentry->name_len = len; strcpy(pentry->name,name); pentry->file_type = mode; pentry->rec_len = 8 + len; pentry->inode = new_inode(); write_block_data(dir->ext2_inode.i_block[dir_datablocks],buf);//更新该数据块 if((m_inode=(struct inode*)malloc(sizeof(struct inode))) != NULL){ get_inode_data(pentry->inode,m_inode); m_inode->ext2_inode.i_block[0] = UINT_MAX;//表示该节点是目录节点 m_inode->ext2_inode.i_block[1] = new_block();//为每个目录节点预分配一块数据块,存放目录项 m_inode->ext2_inode.i_blocks = 1; write_inode_data(pentry->inode,m_inode); free(m_inode); return 1; } return -1; }
/* * decode decodes one line of the type structure named str into the * a parseinfo block called pi. depth is the current depth which may be 0. * * newName is set in case of ARRAY (to the empty string) or CONTAINER. In this * case is set to the LIKE parameter or to the empty string. * * Leading and trailing spaces are ignored completely, "INDIRECTFLOAT32" is * acceptable. Differences in case are ignored. * * THE GENERATED TYPE MAY HAVE AN ILLEGAL BIT SIZE. IT ISN'T CHECKED ALWAYS! * * Return values: * GCI_OK: Line understood, *pi filled. * GCI_UnsupportedType: Wrong type of input, e.g. FLOAT31 or the empty string. * GCI_NoBaseType: The type won't fit the requirements for basic types. */ static GCI_result decode( void *hidden, const GCI_str *str, GCI_parseinfo *pi, int depth, GCI_str *newName ) { const char *ptr = GCI_ccontent( str ); int size = GCI_strlen( str ); /* * Chop off leading and trailing spaces. We really need it. */ while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } while ( ( size > 0 ) && GCI_isspace( ptr[size - 1] ) ) size--; memset( pi, 0, sizeof( GCI_parseinfo ) ); if ( ( pi->type = checkname( &ptr, &size ) ) == GCI_unknown ) return GCI_UnsupportedType; if ( pi->type == GCI_indirect ) { while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } pi->type = checkname( &ptr, &size ); if ( ( pi->type == GCI_unknown ) || ( pi->type == GCI_indirect ) ) return GCI_UnsupportedType; pi->indirect = 1; } else pi->indirect = 0; /* * Check for a size operand. */ while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } /* * We may have a size operand only if not an array or container is * processed! * This implementation shall support plain types like "INTEGER" without * any bit size. */ switch ( pi->type ) { case GCI_container: if ( size > 0 ) { GCI_str tmp; if ( checkname( &ptr, &size ) != GCI_like ) return GCI_UnsupportedType; while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } if ( size == 0 ) { /* * Single "like" after "container". */ return GCI_UnsupportedType; } while ( GCI_isspace( ptr[size - 1] ) ) size--; /* * Cut off a final dot, we append one later. */ if ( ptr[size - 1] == '.' ) { /* * Check for single "." as stem. */ if ( --size == 0 ) return GCI_UnsupportedType; } if ( GCI_stralloc( hidden, newName, size + 256 ) != GCI_OK ) return GCI_NoMemory; GCI_strfromascii( &tmp, (char *) ptr, size ); GCI_strsetlen( &tmp, size ); GCI_strcpy( newName, &tmp ); size = 0; } /* fall through */ case GCI_array: if ( size > 0 ) return GCI_UnsupportedType; if ( ( depth == 0 ) && !pi->indirect ) { if ( GCI_content( newName ) != NULL ) GCI_strfree( hidden, newName ); return GCI_NoBaseType; } pi->size = 0; return GCI_OK; case GCI_integer: if ( size == 0 ) pi->size = 8 * sizeof( int ); break; case GCI_unsigned: if ( size == 0 ) pi->size = 8 * sizeof( unsigned ); break; case GCI_float: if ( size == 0 ) pi->size = 8 * sizeof( double ); /* surprised? */ break; case GCI_char: if ( size == 0 ) pi->size = 8 * 1; /* always, even in unicode or utf8 systems */ break; case GCI_string: if ( size == 0 ) /* length must be supplied */ return GCI_UnsupportedType; break; // JLF needed for portability: aliases which depend on the system & bitness. // Each alias defines a type and a size, no size accepted after these aliases. case GCI_long: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( long ); break; case GCI_llong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( long long ); break; case GCI_pointer: // opaque if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( void* ); break; case GCI_size_t: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( size_t ); break; case GCI_ssize_t: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( ssize_t ); break; case GCI_ulong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( unsigned long ); break; case GCI_ullong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( unsigned long long ); break; default: return GCI_UnsupportedType; } if ( size > 0 ) { if ( GCI_string2bin( hidden, ptr, size, &pi->size, sizeof( pi->size ), GCI_unsigned ) != GCI_OK ) return GCI_UnsupportedType; } if ( ( pi->type == GCI_string ) && ( pi->size > 0 ) ) return GCI_OK; /* * A byte has 8 bit, always! We don't support PDP10. */ if ( pi->type != GCI_string ) { if ( pi->size % 8 ) return GCI_UnsupportedType; pi->size /= 8; } return GCI_validate( pi->size, pi->type, depth || pi->indirect ); }