Exemplo n.º 1
0
#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");
}
Exemplo n.º 2
0
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 */
}
Exemplo n.º 3
0
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;
    }
  }
}
Exemplo n.º 4
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");

}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
/*
 *	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);
}
Exemplo n.º 7
0
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);
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
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 */
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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);
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
/*
 * 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 );
}