postgres 之 initdb 源码分析 三

来源:互联网 发布:测试网络丢包软件 编辑:程序博客网 时间:2024/05/26 04:19

2.4 函数 getopt_long

文件 Getopt_long.c
作用 验证输入参数的合法性(代码这么长,主要是针对一些列异常输入参数)
在initdb.c中,传入的参数为: while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
该函数依次验证argv[i]  1<=i <argc
另外 "dD:E:kL:nNU:WA:sST:X:", 这种写法也是有针对性的。后面无冒号则不带参数,否则必须带参数

/* * getopt_long *Parse argc/argv argument vector, with long options. * * This implementation does not use optreset.  Instead, we guarantee that * it can be restarted on a new argv array after a previous call returned -1, * if the caller resets optind to 1 before the first call of the new series. * (Internally, this means we must be sure to reset "place" to EMSG before * returning -1.) */intgetopt_long(int argc, char *const argv[],const char *optstring,const struct option * longopts, int *longindex){static char *place = EMSG;/* option letter processing */char   *oli;/* option letter list index */if (!*place){/* update scanning pointer */if (optind >= argc){place = EMSG;return -1;}place = argv[optind];if (place[0] != '-'){place = EMSG;return -1;}place++;if (place[0] && place[0] == '-' && place[1] == '\0'){/* found "--" */++optind;place = EMSG;return -1;}if (place[0] && place[0] == '-' && place[1]){/* long option */size_tnamelen;inti;place++;namelen = strcspn(place, "=");for (i = 0; longopts[i].name != NULL; i++){if (strlen(longopts[i].name) == namelen&& strncmp(place, longopts[i].name, namelen) == 0){if (longopts[i].has_arg){if (place[namelen] == '=')optarg = place + namelen + 1;else if (optind < argc - 1){optind++;optarg = argv[optind];}else{if (optstring[0] == ':')return BADARG;if (opterr)fprintf(stderr,   "%s: option requires an argument -- %s\n",argv[0], place);place = EMSG;optind++;return BADCH;}}else{optarg = NULL;if (place[namelen] != 0){/* XXX error? */}}optind++;if (longindex)*longindex = i;place = EMSG;if (longopts[i].flag == NULL)return longopts[i].val;else{*longopts[i].flag = longopts[i].val;return 0;}}}if (opterr && optstring[0] != ':')fprintf(stderr,"%s: illegal option -- %s\n", argv[0], place);place = EMSG;optind++;return BADCH;}}/* short option */optopt = (int) *place++;oli = strchr(optstring, optopt);if (!oli){if (!*place)++optind;if (opterr && *optstring != ':')fprintf(stderr,"%s: illegal option -- %c\n", argv[0], optopt);return BADCH;}if (oli[1] != ':'){/* don't need argument */optarg = NULL;if (!*place)++optind;}else{/* need an argument */if (*place)/* no white space */optarg = place;else if (argc <= ++optind){/* no arg */place = EMSG;if (*optstring == ':')return BADARG;if (opterr)fprintf(stderr,"%s: option requires an argument -- %c\n",argv[0], optopt);return BADCH;}else/* white space */optarg = argv[optind];place = EMSG;++optind;}return optopt;}
optarg 会传送到initdb.c中 ,其值为各个 参数对应的值 (如 -D ./data 那么optarg 为“./data”)

2.5 函数 pg_strdup (char *)

pg中改写了很多C标准库中的函数,改写的原因为增强程序的健壮性,减少出现异常的几率
pg_strdup()函数和标准库函数strdup差别在于对输入参数为空(NULL)的检测

/* * "Safe" wrapper around strdup(). */char *pg_strdup(const char *in){char   *tmp;if (!in){fprintf(stderr,_("cannot duplicate null pointer (internal error)\n"));exit(EXIT_FAILURE);}tmp = strdup(in);if (!tmp){fprintf(stderr, _("out of memory\n"));exit(EXIT_FAILURE);}return tmp;}

2.6 函数 setup_pgdata (void)

文件initdb.c
若initdb时没指定-D 则会默认寻找安装路径PGDATA,但是若环境变量中无此变量则报错

voidsetup_pgdata(void){char   *pgdata_get_env,   *pgdata_set_env;if (strlen(pg_data) == 0){pgdata_get_env = getenv("PGDATA");if (pgdata_get_env && strlen(pgdata_get_env)){/* PGDATA found */pg_data = pg_strdup(pgdata_get_env);}else{fprintf(stderr,_("%s: no data directory specified\n"  "You must identify the directory where the data for this database system\n"  "will reside.  Do this with either the invocation option -D or the\n"  "environment variable PGDATA.\n"),progname);exit(1);}}pgdata_native = pg_strdup(pg_data);canonicalize_path(pg_data);/* * we have to set PGDATA for postgres rather than pass it on the command * line to avoid dumb quoting problems on Windows, and we would especially * need quotes otherwise on Windows because paths there are most likely to * have embedded spaces. */pgdata_set_env = pg_malloc(8 + strlen(pg_data));sprintf(pgdata_set_env, "PGDATA=%s", pg_data);putenv(pgdata_set_env);}

2.6.1 函数pg_malloc()

(1)malloc(0) 是允许的,这是因为Linux中malloc有一个下限值16Bytes,注意malloc(-1)是禁止的 --这个是从百度百科看到的。
(2)If size is zero, the return value depends on the particular library implementation (it may or may not be a null pointer), but the returned pointer shall not be dereferenced.  --这个来自 http://www.cplusplus.com/reference/cstdlib/malloc/?kw=malloc
(3)malloc() allocates size bytes and returns a pointer to the allocated memory.  The memory is not cleared.  If size
       is 0, then malloc() returns either NULL, or a unique pointer value that  can  later  be  successfully  passed  to
       free().  --来自 man malloc
这样处理是为了防止size为0 

void *pg_malloc(size_t size){void   *tmp;/* Avoid unportable behavior of malloc(0) */if (size == 0)size = 1;tmp = malloc(size);if (!tmp){fprintf(stderr, _("out of memory\n"));exit(EXIT_FAILURE);}return tmp;}





0 0
原创粉丝点击