bool endswith(const char *path1, const char *path2) { if (canonpath(path1, PBUF)) { int len1 = strlen(PBUF); int len2 = strlen(path2); if (len1 < len2) return false; int i = len1 - len2; int j = 0; if (PBUF[0] == '/' && i > 0 && path2[j] != '/' && PBUF[i - 1] != '/') { // A: /tmp/atest.c // B: test.c return false; } while (i < len1 && j < len2 && PBUF[i] == path2[j]) { i++; j++; } if (i != len1) { return false; } return true; } else return false; }
int main(int argc,char *argv[]) { bool follow = false; int opt; while((opt = getopt(argc,argv,"f")) != -1) { switch(opt) { case 'f': follow = true; break; default: usage(argv[0]); } } if(optind >= argc) usage(argv[0]); for(int i = optind; i < argc; ++i) { char tmp[MAX_PATH_LEN]; if(follow) { if(canonpath(tmp,sizeof(tmp),argv[i]) < 0) { printe("readlink for '%s' failed",argv[i]); continue; } puts(tmp); } else { if(!islink(argv[i])) printe("'%s' is no symbolic link",argv[i]); else if(readlink(argv[i],tmp,sizeof(tmp)) < 0) printe("readlink for '%s' failed",argv[i]); else puts(tmp); } } return EXIT_SUCCESS; }
bool pathneq(const char *path1, const char *path2, int n) { if (canonpath(path1, PBUF)) { return strcmp(stripname(PBUF, n), path2) == 0; } else return false; }
/** * realpath: get the complete path */ char * realpath(const char *in_path, char *out_path) { #ifdef __DJGPP__ /* * I don't use _fixpath or _truename in LFN because neither guarantee * a complete long name. This is mainly DOS's fault, since the cwd can * be a mixture of long and short components. */ if (_USE_LFN) { strlimcpy(out_path, in_path, MAXPATHLEN); canonpath(out_path); } else _fixpath(in_path, out_path); #else _fullpath(out_path, in_path, MAXPATHLEN); canonpath(out_path); #endif return out_path; }
bool Matcher::initName(StringRef fname) { char *canon = canonpath(fname.data(), NULL); if (canon == NULL) { errs() << "Warning: patchname is NULL\n"; return false; } filename.assign(canon); free(canon); patchname = stripname(filename.c_str(), patchstrips); if (strlen(patchname) == 0) { errs() << "Warning: patchname is empty after strip\n"; return false; } return true; }
/* * return a relative path from @from to @to * result should be freed */ char * relative_path_to(char *from, char *to, int *err) { int from_nodes, common; char *to_absolute, __to_absolute[PATH_MAX]; char *from_absolute, __from_absolute[PATH_MAX]; char *up, *common_target_path, *relative_path; *err = 0; up = NULL; to_absolute = NULL; from_absolute = NULL; relative_path = NULL; if (strnlen(to, MAX_NAME_LEN) == MAX_NAME_LEN || strnlen(from, MAX_NAME_LEN) == MAX_NAME_LEN) { EPRINTF("invalid input; max path length is %d\n", MAX_NAME_LEN); *err = -ENAMETOOLONG; return NULL; } to_absolute = canonpath(to, __to_absolute); if (!to_absolute) { EPRINTF("failed to get absolute path of %s\n", to); *err = -errno; goto out; } from_absolute = canonpath(from, __from_absolute); if (!from_absolute) { EPRINTF("failed to get absolute path of %s\n", from); *err = -errno; goto out; } if (strnlen(to_absolute, MAX_NAME_LEN) == MAX_NAME_LEN || strnlen(from_absolute, MAX_NAME_LEN) == MAX_NAME_LEN) { EPRINTF("invalid input; max path length is %d\n", MAX_NAME_LEN); *err = -ENAMETOOLONG; goto out; } /* count nodes in source path */ from_nodes = count_nodes(from_absolute); /* count nodes in common */ common = count_common_nodes(to_absolute + 1, from_absolute + 1); if (common < 0) { EPRINTF("failed to count common nodes of %s and %s: %d\n", to_absolute, from_absolute, common); *err = common; goto out; } /* move up to common node */ up = up_nodes(from_nodes - common - 1); if (!up) { EPRINTF("failed to allocate relative path for %s: %d\n", from_absolute, -ENOMEM); *err = -ENOMEM; goto out; } /* get path from common node to target */ common_target_path = node_offset(to_absolute, common + 1); if (!common_target_path) { EPRINTF("failed to find common target path to %s: %d\n", to_absolute, -EINVAL); *err = -EINVAL; goto out; } /* get relative path */ if (asprintf(&relative_path, "%s%s", up, common_target_path) == -1) { EPRINTF("failed to construct final path %s%s: %d\n", up, common_target_path, -ENOMEM); relative_path = NULL; *err = -ENOMEM; goto out; } out: sfree(up); return relative_path; }
/* * Need to make it more obvious that one cannot get through here * without the right flags set */ int pledge_namei(struct proc *p, struct nameidata *ni, char *origpath) { char path[PATH_MAX]; int error; if ((p->p_p->ps_flags & PS_PLEDGE) == 0 || (p->p_p->ps_flags & PS_COREDUMP)) return (0); if (!ni || (ni->ni_pledge == 0)) panic("ni_pledge"); /* Doing a permitted execve() */ if ((ni->ni_pledge & PLEDGE_EXEC) && (p->p_p->ps_pledge & PLEDGE_EXEC)) return (0); error = canonpath(origpath, path, sizeof(path)); if (error) return (error); /* Detect what looks like a mkstemp(3) family operation */ if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) && (p->p_pledge_syscall == SYS_open) && (ni->ni_pledge & PLEDGE_CPATH) && strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { return (0); } /* Allow unlinking of a mkstemp(3) file... * Good opportunity for strict checks here. */ if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) && (p->p_pledge_syscall == SYS_unlink) && strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { return (0); } /* Whitelisted paths */ switch (p->p_pledge_syscall) { case SYS_access: /* tzset() needs this. */ if ((ni->ni_pledge == PLEDGE_RPATH) && strcmp(path, "/etc/localtime") == 0) return (0); /* when avoiding YP mode, getpw* functions touch this */ if (ni->ni_pledge == PLEDGE_RPATH && strcmp(path, "/var/run/ypbind.lock") == 0) { if (p->p_p->ps_pledge & PLEDGE_GETPW) return (0); else return (pledge_fail(p, error, PLEDGE_GETPW)); } break; case SYS_open: /* daemon(3) or other such functions */ if ((ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && strcmp(path, "/dev/null") == 0) { return (0); } /* readpassphrase(3), getpass(3) */ if ((p->p_p->ps_pledge & PLEDGE_TTY) && (ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && strcmp(path, "/dev/tty") == 0) { return (0); } /* getpw* and friends need a few files */ if ((ni->ni_pledge == PLEDGE_RPATH) && (p->p_p->ps_pledge & PLEDGE_GETPW)) { if (strcmp(path, "/etc/spwd.db") == 0) return (EPERM); /* don't call pledge_fail */ if (strcmp(path, "/etc/pwd.db") == 0) return (0); if (strcmp(path, "/etc/group") == 0) return (0); if (strcmp(path, "/etc/netid") == 0) return (0); } /* DNS needs /etc/{resolv.conf,hosts,services}. */ if ((ni->ni_pledge == PLEDGE_RPATH) && (p->p_p->ps_pledge & PLEDGE_DNS)) { if (strcmp(path, "/etc/resolv.conf") == 0) return (0); if (strcmp(path, "/etc/hosts") == 0) return (0); if (strcmp(path, "/etc/services") == 0) return (0); } if ((ni->ni_pledge == PLEDGE_RPATH) && (p->p_p->ps_pledge & PLEDGE_GETPW)) { if (strcmp(path, "/var/run/ypbind.lock") == 0) { /* * XXX * The current hack for YP support in "getpw" * is to enable some "inet" features until * next pledge call. This is not considered * worse than pre-pledge, but is a work in * progress, needing a clever design. */ p->p_p->ps_pledge |= PLEDGE_YPACTIVE; return (0); } if (strncmp(path, "/var/yp/binding/", sizeof("/var/yp/binding/") - 1) == 0) return (0); } /* tzset() needs these. */ if ((ni->ni_pledge == PLEDGE_RPATH) && strncmp(path, "/usr/share/zoneinfo/", sizeof("/usr/share/zoneinfo/") - 1) == 0) return (0); if ((ni->ni_pledge == PLEDGE_RPATH) && strcmp(path, "/etc/localtime") == 0) return (0); break; case SYS_readlink: /* Allow /etc/malloc.conf for malloc(3). */ if ((ni->ni_pledge == PLEDGE_RPATH) && strcmp(path, "/etc/malloc.conf") == 0) return (0); break; case SYS_stat: /* DNS needs /etc/resolv.conf. */ if ((ni->ni_pledge == PLEDGE_RPATH) && (p->p_p->ps_pledge & PLEDGE_DNS) && strcmp(path, "/etc/resolv.conf") == 0) return (0); break; } /* * Ensure each flag of p_pledgenote has counterpart allowing it in * ps_pledge */ if (ni->ni_pledge & ~p->p_p->ps_pledge) return (pledge_fail(p, EPERM, (ni->ni_pledge & ~p->p_p->ps_pledge))); return (0); }
/** * Given a url this functions tries to find the physical path on the server. * @cl the client that made the request * @url the requested URL * @return NULL on error */ static struct path_info *path_lookup(struct client *cl, const char *url) { static char path_phys[PATH_MAX]; static char path_info[PATH_MAX]; static struct path_info p; int docroot_len = strlen(DOCUMENT_ROOT); char *pathptr = NULL; bool slash; int i = 0; int len; struct stat s; /* Return NULL when the URL is undefined */ if (url == NULL) return NULL; memset(&p, 0, sizeof(p)); path_phys[0] = 0; path_info[0] = 0; /* Start the canonical path with the document root */ strcpy(uh_buf, DOCUMENT_ROOT); /* Separate query string from url */ if ((pathptr = strchr(url, '?')) != NULL) { p.query = pathptr[1] ? pathptr + 1 : NULL; /* URL decode component without query */ if (pathptr > url) { if (uh_urldecode(&uh_buf[docroot_len], sizeof(uh_buf) - docroot_len - 1, url, pathptr - url ) < 0) return NULL; } } /* Decode the full url when there is no querystring */ else if (uh_urldecode(&uh_buf[docroot_len], sizeof(uh_buf) - docroot_len - 1, url, strlen(url) ) < 0) return NULL; /* Create canonical path */ len = strlen(uh_buf); slash = len && uh_buf[len - 1] == '/'; len = min(len, sizeof(path_phys) - 1); for (i = len; i >= 0; i--) { char ch = uh_buf[i]; bool exists; if (ch != 0 && ch != '/') continue; uh_buf[i] = 0; exists = !!canonpath(uh_buf, path_phys); uh_buf[i] = ch; if (!exists) continue; /* Test the current path */ if (stat(path_phys, &p.stat)) continue; snprintf(path_info, sizeof(path_info), "%s", uh_buf + i); break; } /* Check whether found path is within docroot */ if (strncmp(path_phys, DOCUMENT_ROOT, docroot_len) != 0 || (path_phys[docroot_len] != 0 && path_phys[docroot_len] != '/')){ return NULL; } /* Check if the found file is a regular file */ if (p.stat.st_mode & S_IFREG) { p.root = DOCUMENT_ROOT; p.phys = path_phys; p.name = &path_phys[docroot_len]; p.info = path_info[0] ? path_info : NULL; return &p; } /* Make sure it is not a directory */ if (!(p.stat.st_mode & S_IFDIR)){ return NULL; } if (path_info[0]){ return NULL; } pathptr = path_phys + strlen(path_phys); /* ensure trailing slash */ if (pathptr[-1] != '/') { pathptr[0] = '/'; pathptr[1] = 0; pathptr++; } /* if requested url resolves to a directory and a trailing slash is missing in the request url, redirect the client to the same url with trailing slash appended */ if (!slash) { write_http_header(cl, 302, "Found"); ustream_printf(cl->us, "Content-Length: 0\r\n"); ustream_printf(cl->us, "Location: %s%s%s\r\n\r\n", &path_phys[docroot_len], p.query ? "?" : "", p.query ? p.query : ""); request_done(cl); p.redirected = 1; return &p; } /* Check if the folder contains an index file */ len = path_phys + sizeof(path_phys) - pathptr - 1; if(strlen(INDEX_FILE) <= len){ strcpy(pathptr, INDEX_FILE); if (!stat(path_phys, &s) && (s.st_mode & S_IFREG)) { memcpy(&p.stat, &s, sizeof(p.stat)); } else { /* Stop when strcpy is not needed */ *pathptr = 0; } } p.root = DOCUMENT_ROOT; p.phys = path_phys; p.name = &path_phys[docroot_len]; return p.phys ? &p : NULL; }
int vhd_util_snapshot(int argc, char **argv) { vhd_flag_creat_t flags; int c, err, prt_raw, limit, empty_check; #ifdef XS_VHD uint8_t encrypt_method; #endif char *name, *pname, *backing; char *ppath, __ppath[PATH_MAX]; uint64_t size, msize; vhd_context_t vhd; name = NULL; pname = NULL; ppath = NULL; backing = NULL; size = 0; msize = 0; flags = 0; limit = 0; empty_check = 1; #ifdef XS_VHD encrypt_method = 0; #endif if (!argc || !argv) { err = -EINVAL; goto usage; } optind = 0; #ifndef XS_VHD while ((c = getopt(argc, argv, "n:p:S:l:meh")) != -1) { #else while ((c = getopt(argc, argv, "n:p:S:E:l:meh")) != -1) { #endif switch (c) { case 'n': name = optarg; break; case 'p': pname = optarg; break; case 'S': msize = strtoull(optarg, NULL, 10); #ifdef XS_VHD case 'E': encrypt_method = atoi(optarg); break; #endif case 'l': limit = strtol(optarg, NULL, 10); break; case 'm': vhd_flag_set(flags, VHD_FLAG_CREAT_PARENT_RAW); break; case 'e': empty_check = 0; break; case 'h': err = 0; goto usage; default: err = -EINVAL; goto usage; } } if (!name || !pname || optind != argc) { err = -EINVAL; goto usage; } ppath = canonpath(pname, __ppath); if (!ppath) return -errno; if (vhd_flag_test(flags, VHD_FLAG_CREAT_PARENT_RAW) || !empty_check) { backing = strdup(ppath); if (!backing) { err = -ENOMEM; goto out; } } else { err = vhd_util_find_snapshot_target(ppath, &backing, &prt_raw); if (err) { backing = NULL; goto out; } /* * if the sizes of the parent chain are non-uniform, we need to * pick the right size: that of the supplied parent */ if (strcmp(ppath, backing)) { err = vhd_open(&vhd, ppath, VHD_OPEN_RDONLY); if (err) goto out; size = vhd.footer.curr_size; vhd_close(&vhd); } if (prt_raw) vhd_flag_set(flags, VHD_FLAG_CREAT_PARENT_RAW); } if (limit && !vhd_flag_test(flags, VHD_FLAG_CREAT_PARENT_RAW)) { int depth; err = vhd_util_check_depth(backing, &depth); if (err) printf("error checking snapshot depth: %d\n", err); else if (depth + 1 > limit) { err = -ENOSPC; printf("snapshot depth exceeded: " "current depth: %d, limit: %d\n", depth, limit); } if (err) goto out; } #ifndef XS_VHD err = vhd_snapshot(name, size, backing, msize << 20, flags); #else err = vhd_snapshot(name, size, backing, msize << 20, flags, encrypt_method); #endif out: free(backing); return err; usage: printf("options: <-n name> <-p parent name> [-l snapshot depth limit]" " [-m parent_is_raw] [-S size (MB) for metadata preallocation " "(see vhd-util resize)] [-e link to supplied parent name even " "if it's empty] [-h help]\n"); return err; }
static void test_canonpath(void) { char path[MAX_PATH_LEN]; size_t count; test_caseStart("Testing canonpath"); setenv("CWD","/"); count = canonpath(path,sizeof(path),"/"); test_assertUInt(count,SSTRLEN("/")); test_assertStr(path,"/"); count = canonpath(path,sizeof(path),"/bin/ls"); test_assertUInt(count,SSTRLEN("/bin/ls")); test_assertStr(path,"/bin/ls"); count = canonpath(path,sizeof(path),"/../bin/../.././home"); test_assertUInt(count,SSTRLEN("/home")); test_assertStr(path,"/home"); count = canonpath(path,sizeof(path),"bin/..///.././home"); test_assertUInt(count,SSTRLEN("/home")); test_assertStr(path,"/home"); count = canonpath(path,sizeof(path),"bin/./ls"); test_assertUInt(count,SSTRLEN("/bin/ls")); test_assertStr(path,"/bin/ls"); setenv("CWD","/home"); count = canonpath(path,sizeof(path),"hrniels/./scripts"); test_assertUInt(count,SSTRLEN("/home/hrniels/scripts")); test_assertStr(path,"/home/hrniels/scripts"); setenv("CWD","/home/"); count = canonpath(path,sizeof(path),"hrniels/./scripts"); test_assertUInt(count,SSTRLEN("/home/hrniels/scripts")); test_assertStr(path,"/home/hrniels/scripts"); count = canonpath(path,sizeof(path),".."); test_assertUInt(count,SSTRLEN("/")); test_assertStr(path,"/"); count = canonpath(path,sizeof(path),"../../."); test_assertUInt(count,SSTRLEN("/")); test_assertStr(path,"/"); count = canonpath(path,sizeof(path),"./../bin"); test_assertUInt(count,SSTRLEN("/bin")); test_assertStr(path,"/bin"); count = canonpath(path,3,"/"); if(count > 3) test_caseFailed("Copied too much"); count = canonpath(path,8,"/bin/ls"); if(count > 8) test_caseFailed("Copied too much"); count = canonpath(path,8,"/bin/../home"); if(count > 8) test_caseFailed("Copied too much"); count = canonpath(path,8,"///../bin/ls"); if(count > 8) test_caseFailed("Copied too much"); test_caseSucceeded(); }
int main(int argc, char **argv) { char dbpath[MAXPATHLEN]; char cwd[MAXPATHLEN]; STRBUF *sb = strbuf_open(0); int optchar; int option_index = 0; STATISTICS_TIME *tim; while ((optchar = getopt_long(argc, argv, "cd:f:iuIn:oOqvwse", long_options, &option_index)) != EOF) { switch (optchar) { case 0: /* already flags set */ break; case OPT_CONFIG: show_config = 1; if (optarg) config_name = optarg; break; case OPT_GTAGSCONF: gtagsconf = optarg; break; case OPT_GTAGSLABEL: gtagslabel = optarg; break; case OPT_PATH: do_path = 1; if (!strcmp("absolute", optarg)) convert_type = PATH_ABSOLUTE; else if (!strcmp("relative", optarg)) convert_type = PATH_RELATIVE; else if (!strcmp("through", optarg)) convert_type = PATH_THROUGH; else die("Unknown path type."); break; case OPT_SINGLE_UPDATE: iflag++; single_update = optarg; break; case OPT_ENCODE_PATH: if (strlen(optarg) > 255) die("too many encode chars."); if (strchr(optarg, '/') || strchr(optarg, '.')) die("cannot encode '/' and '.' in the path."); set_encode_chars((unsigned char *)optarg); break; case 'c': cflag++; break; case 'd': dump_target = optarg; break; case 'f': file_list = optarg; break; case 'i': iflag++; break; case 'u': uflag++; iflag++; break; case 'I': Iflag++; break; case 'o': /* * Though the -o(--omit-gsyms) was removed, this code * is left for compatibility. */ break; case 'O': Oflag++; break; case 'q': qflag++; setquiet(); break; case 'w': wflag++; break; case 'v': vflag++; setverbose(); break; default: usage(); break; } } if (gtagsconf) { char path[MAXPATHLEN]; if (realpath(gtagsconf, path) == NULL) die("%s not found.", gtagsconf); set_env("GTAGSCONF", path); } if (gtagslabel) { set_env("GTAGSLABEL", gtagslabel); } if (qflag) vflag = 0; if (show_version) version(NULL, vflag); if (show_help) help(); argc -= optind; argv += optind; /* If dbpath is specified, -O(--objdir) option is ignored. */ if (argc > 0) Oflag = 0; if (show_config) { if (config_name) printconf(config_name); else fprintf(stdout, "%s\n", getconfline()); exit(0); } else if (do_path) { /* * This is the main body of path filter. * This code extract path name from tag line and * replace it with the relative or the absolute path name. * * By default, if we are in src/ directory, the output * should be converted like follws: * * main 10 ./src/main.c main(argc, argv)\n * main 22 ./libc/func.c main(argc, argv)\n * v * main 10 main.c main(argc, argv)\n * main 22 ../libc/func.c main(argc, argv)\n * * Similarly, the --path=absolute option specified, then * v * main 10 /prj/xxx/src/main.c main(argc, argv)\n * main 22 /prj/xxx/libc/func.c main(argc, argv)\n */ STRBUF *ib = strbuf_open(MAXBUFLEN); CONVERT *cv; char *ctags_x; if (argc < 3) die("gtags --path: 3 arguments needed."); cv = convert_open(convert_type, FORMAT_CTAGS_X, argv[0], argv[1], argv[2], stdout); while ((ctags_x = strbuf_fgets(ib, stdin, STRBUF_NOCRLF)) != NULL) convert_put(cv, ctags_x); convert_close(cv); strbuf_close(ib); exit(0); } else if (dump_target) { /* * Dump a tag file. */ DBOP *dbop = NULL; const char *dat = 0; int is_gpath = 0; char* target_file = NULL; if (!test("f", dump_target)) { target_file = strchr(dump_target, ':'); if (target_file == NULL) die("file '%s' not found", dump_target); *target_file++ = 0; //move to the next char, which starts the target file. if (!test("f", dump_target)) { die("file '%s' not found.", dump_target); } } if ((dbop = dbop_open(dump_target, 0, 0, DBOP_RAW)) == NULL) die("file '%s' is not a tag file.", dump_target); /* * The file which has a NEXTKEY record is GPATH. */ if (dbop_get(dbop, NEXTKEY)) is_gpath = 1; if (target_file && !is_gpath) { die("dump target_file can only be used with GPATH"); } if (target_file) { dat = dbop_get(dbop, target_file); if (dat == NULL) { die("target_file %s not found in GPATH", target_file); } time_t t = gpath_mtime(dbop, target_file); printf("%d\n", t); } else { for (dat = dbop_first(dbop, NULL, NULL, 0); dat != NULL; dat = dbop_next(dbop)) { const char *flag = is_gpath ? dbop_getflag(dbop) : ""; if (*flag) if (is_gpath) { time_t t = gpath_mtime(dbop, dbop->lastkey); printf("%s\t%s\t%s\t%s\n", dbop->lastkey, dat, flag, ctime(&t)); } else printf("%s\t%s\t%s\n", dbop->lastkey, dat, flag); else printf("%s\t%s\n", dbop->lastkey, dat); } } dbop_close(dbop); exit(0); } else if (Iflag) { if (!usable("mkid")) die("mkid not found."); } /* * If 'gtags.files' exists, use it as a file list. * If the file_list other than "-" is given, it must be readable file. */ if (file_list == NULL && test("f", GTAGSFILES)) file_list = GTAGSFILES; if (file_list && strcmp(file_list, "-")) { if (test("d", file_list)) die("'%s' is a directory.", file_list); else if (!test("f", file_list)) die("'%s' not found.", file_list); else if (!test("r", file_list)) die("'%s' is not readable.", file_list); } /* * Regularize the path name for single updating (--single-update). */ if (single_update) { static char regular_path_name[MAXPATHLEN]; char *p = single_update; if (!test("f", p)) die("'%s' not found.", p); if (isabspath(p)) die("--single-update requires relative path name."); if (!(p[0] == '.' && p[1] == '/')) { snprintf(regular_path_name, MAXPATHLEN, "./%s", p); p = regular_path_name; } single_update = p; } if (!getcwd(cwd, MAXPATHLEN)) die("cannot get current directory."); canonpath(cwd); /* * Decide directory (dbpath) in which gtags make tag files. * * Gtags create tag files at current directory by default. * If dbpath is specified as an argument then use it. * If the -i option specified and both GTAGS and GRTAGS exists * at one of the candidate directories then gtags use existing * tag files. */ if (iflag) { if (argc > 0) realpath(*argv, dbpath); else if (!gtagsexist(cwd, dbpath, MAXPATHLEN, vflag)) strlimcpy(dbpath, cwd, sizeof(dbpath)); } else { if (argc > 0) realpath(*argv, dbpath); else if (Oflag) { char *objdir = getobjdir(cwd, vflag); if (objdir == NULL) die("Objdir not found."); strlimcpy(dbpath, objdir, sizeof(dbpath)); } else strlimcpy(dbpath, cwd, sizeof(dbpath)); } if (iflag && (!test("f", makepath(dbpath, dbname(GTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GRTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GPATH), NULL)))) { if (wflag) warning("GTAGS, GRTAGS or GPATH not found. -i option ignored."); iflag = 0; } if (!test("d", dbpath)) die("directory '%s' not found.", dbpath); if (vflag) fprintf(stderr, "[%s] Gtags started.\n", now()); /* * load configuration file. */ openconf(); if (getconfb("extractmethod")) extractmethod = 1; strbuf_reset(sb); if (getconfs("langmap", sb)) langmap = check_strdup(strbuf_value(sb)); strbuf_reset(sb); if (getconfs("gtags_parser", sb)) gtags_parser = check_strdup(strbuf_value(sb)); /* * initialize parser. */ if (vflag && gtags_parser) fprintf(stderr, " Using plug-in parser.\n"); parser_init(langmap, gtags_parser); if (vflag && file_list) fprintf(stderr, " Using '%s' as a file list.\n", file_list); /* * Start statistics. */ init_statistics(); /* * incremental update. */ if (iflag) { /* * Version check. If existing tag files are old enough * gtagsopen() abort with error message. */ GTOP *gtop = gtags_open(dbpath, cwd, GTAGS, GTAGS_MODIFY, 0); gtags_close(gtop); /* * GPATH is needed for incremental updating. * Gtags check whether or not GPATH exist, since it may be * removed by mistake. */ if (!test("f", makepath(dbpath, dbname(GPATH), NULL))) die("Old version tag file found. Please remake it."); (void)incremental(dbpath, cwd); print_statistics(statistics); exit(0); } /* * create GTAGS and GRTAGS */ createtags(dbpath, cwd); /* * create idutils index. */ if (Iflag) { tim = statistics_time_start("Time of creating ID"); if (vflag) fprintf(stderr, "[%s] Creating indexes for idutils.\n", now()); strbuf_reset(sb); strbuf_puts(sb, "mkid"); if (vflag) strbuf_puts(sb, " -v"); strbuf_sprintf(sb, " --file='%s/ID'", dbpath); if (vflag) { #ifdef __DJGPP__ if (is_unixy()) /* test for 4DOS as well? */ #endif strbuf_puts(sb, " 1>&2"); } else { strbuf_puts(sb, " >/dev/null"); } if (debug) fprintf(stderr, "executing mkid like: %s\n", strbuf_value(sb)); if (system(strbuf_value(sb))) die("mkid failed: %s", strbuf_value(sb)); if (chmod(makepath(dbpath, "ID", NULL), 0644) < 0) die("cannot chmod ID file."); statistics_time_end(tim); } if (vflag) fprintf(stderr, "[%s] Done.\n", now()); closeconf(); strbuf_close(sb); print_statistics(statistics); return 0; }
int main(int argc, char **argv) { char dbpath[MAXPATHLEN]; char cwd[MAXPATHLEN]; STRBUF *sb = strbuf_open(0); int optchar; int option_index = 0; STATISTICS_TIME *tim; /* * Setup GTAGSCONF and GTAGSLABEL environment variable * according to the --gtagsconf and --gtagslabel option. */ preparse_options(argc, argv); /* * Get the project root directory. */ if (!vgetcwd(cwd, MAXPATHLEN)) die("cannot get current directory."); canonpath(cwd); /* * Load configuration file. */ openconf(cwd); configuration(); setenv_from_config(); { char *env = getenv("GTAGS_OPTIONS"); if (env && *env) argv = prepend_options(&argc, argv, env); } logging_arguments(argc, argv); while ((optchar = getopt_long(argc, argv, "cd:f:iIn:oOqvwse", long_options, &option_index)) != EOF) { switch (optchar) { case 0: /* already flags set */ break; case OPT_CONFIG: show_config = 1; if (optarg) config_name = optarg; break; case OPT_GTAGSCONF: case OPT_GTAGSLABEL: /* These options are already parsed in preparse_options() */ break; case OPT_SINGLE_UPDATE: iflag++; single_update = optarg; break; case OPT_ACCEPT_DOTFILES: set_accept_dotfiles(); break; case 'c': cflag++; break; case 'd': dump_target = optarg; break; case 'f': file_list = optarg; break; case 'i': iflag++; break; case 'I': Iflag++; break; case 'o': /* * Though the -o(--omit-gsyms) was removed, this code * is left for compatibility. */ break; case 'O': Oflag++; break; case 'q': qflag++; setquiet(); break; case 'w': wflag++; break; case 'v': vflag++; setverbose(); break; default: usage(); break; } } if (qflag) vflag = 0; if (show_version) version(NULL, vflag); if (show_help) help(); argc -= optind; argv += optind; /* If dbpath is specified, -O(--objdir) option is ignored. */ if (argc > 0) Oflag = 0; if (show_config) { openconf(setupdbpath(0) == 0 ? get_root() : NULL); if (config_name) printconf(config_name); else fprintf(stdout, "%s\n", getconfline()); exit(0); } else if (dump_target) { /* * Dump a tag file. */ DBOP *dbop = NULL; const char *dat = 0; int is_gpath = 0; if (!test("f", dump_target)) die("file '%s' not found.", dump_target); if ((dbop = dbop_open(dump_target, 0, 0, DBOP_RAW)) == NULL) die("file '%s' is not a tag file.", dump_target); /* * The file which has a NEXTKEY record is GPATH. */ if (dbop_get(dbop, NEXTKEY)) is_gpath = 1; for (dat = dbop_first(dbop, NULL, NULL, 0); dat != NULL; dat = dbop_next(dbop)) { const char *flag = is_gpath ? dbop_getflag(dbop) : ""; if (*flag) printf("%s\t%s\t%s\n", dbop->lastkey, dat, flag); else printf("%s\t%s\n", dbop->lastkey, dat); } dbop_close(dbop); exit(0); } else if (Iflag) { #define REQUIRED_MKID_VERSION "4.5" char *p; if (!usable("mkid")) die("mkid not found."); if (read_first_line("mkid --version", sb)) die("mkid cannot executed."); p = strrchr(strbuf_value(sb), ' '); if (p == NULL) die("invalid version string of mkid: %s", strbuf_value(sb)); switch (check_version(p + 1, REQUIRED_MKID_VERSION) #ifdef _WIN32 || strcmp(p + 1, "3.2.99") == 0 #endif ) { case 1: break; /* OK */ case 0: die("mkid version %s or later is required.", REQUIRED_MKID_VERSION); default: die("invalid version string of mkid: %s", strbuf_value(sb)); } } /* * If 'gtags.files' exists, use it as a file list. * If the file_list other than "-" is given, it must be readable file. */ if (file_list == NULL && test("f", GTAGSFILES)) file_list = GTAGSFILES; if (file_list && strcmp(file_list, "-")) { if (test("d", file_list)) die("'%s' is a directory.", file_list); else if (!test("f", file_list)) die("'%s' not found.", file_list); else if (!test("r", file_list)) die("'%s' is not readable.", file_list); } /* * Regularize the path name for single updating (--single-update). */ if (single_update) { static char regular_path_name[MAXPATHLEN]; char *p = single_update; if (!test("f", p)) die("'%s' not found.", p); #if _WIN32 || __DJGPP__ for (; *p; p++) if (*p == '\\') *p = '/'; p = single_update; #define LOCATEFLAG MATCH_AT_FIRST|IGNORE_CASE #else #define LOCATEFLAG MATCH_AT_FIRST #endif if (isabspath(p)) { char *q = locatestring(p, cwd, LOCATEFLAG); if (q && *q == '/') snprintf(regular_path_name, MAXPATHLEN, "./%s", q + 1); else die("path '%s' is out of the project.", p); } else { if (p[0] == '.' && p[1] == '/') snprintf(regular_path_name, MAXPATHLEN, "%s", p); else snprintf(regular_path_name, MAXPATHLEN, "./%s", p); } single_update = regular_path_name; } /* * Decide directory (dbpath) in which gtags make tag files. * * Gtags create tag files at current directory by default. * If dbpath is specified as an argument then use it. * If the -i option specified and both GTAGS and GRTAGS exists * at one of the candidate directories then gtags use existing * tag files. */ if (iflag) { if (argc > 0) realpath(*argv, dbpath); else if (!gtagsexist(cwd, dbpath, MAXPATHLEN, vflag)) strlimcpy(dbpath, cwd, sizeof(dbpath)); } else { if (argc > 0) realpath(*argv, dbpath); else if (Oflag) { char *objdir = getobjdir(cwd, vflag); if (objdir == NULL) die("Objdir not found."); strlimcpy(dbpath, objdir, sizeof(dbpath)); } else strlimcpy(dbpath, cwd, sizeof(dbpath)); } if (iflag && (!test("f", makepath(dbpath, dbname(GTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GRTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GPATH), NULL)))) { if (wflag) warning("GTAGS, GRTAGS or GPATH not found. -i option ignored."); iflag = 0; } if (!test("d", dbpath)) die("directory '%s' not found.", dbpath); if (vflag) fprintf(stderr, "[%s] Gtags started.\n", now()); /* * initialize parser. */ if (vflag && gtags_parser) fprintf(stderr, " Using plug-in parser.\n"); parser_init(langmap, gtags_parser); if (vflag && file_list) fprintf(stderr, " Using '%s' as a file list.\n", file_list); /* * Start statistics. */ init_statistics(); /* * incremental update. */ if (iflag) { /* * Version check. If existing tag files are old enough * gtagsopen() abort with error message. */ GTOP *gtop = gtags_open(dbpath, cwd, GTAGS, GTAGS_MODIFY, 0); gtags_close(gtop); /* * GPATH is needed for incremental updating. * Gtags check whether or not GPATH exist, since it may be * removed by mistake. */ if (!test("f", makepath(dbpath, dbname(GPATH), NULL))) die("Old version tag file found. Please remake it."); (void)incremental(dbpath, cwd); print_statistics(statistics); exit(0); } /* * create GTAGS and GRTAGS */ createtags(dbpath, cwd); /* * create idutils index. */ if (Iflag) { FILE *op; GFIND *gp; const char *path; tim = statistics_time_start("Time of creating ID"); if (vflag) fprintf(stderr, "[%s] Creating indexes for idutils.\n", now()); strbuf_reset(sb); /* * Since idutils stores the value of PWD in ID file, we need to * force idutils to follow our style. */ #if _WIN32 || __DJGPP__ strbuf_puts(sb, "mkid --files0-from=-"); #else strbuf_sprintf(sb, "PWD=%s mkid --files0-from=-", quote_shell(cwd)); #endif if (vflag) strbuf_puts(sb, " -v"); strbuf_sprintf(sb, " --file=%s/ID", quote_shell(dbpath)); if (vflag) { #ifdef __DJGPP__ if (is_unixy()) /* test for 4DOS as well? */ #endif strbuf_puts(sb, " 1>&2"); } else { strbuf_puts(sb, " >" NULL_DEVICE); #ifdef __DJGPP__ if (is_unixy()) /* test for 4DOS as well? */ #endif strbuf_puts(sb, " 2>&1"); } if (debug) fprintf(stderr, "executing mkid like: %s\n", strbuf_value(sb)); op = popen(strbuf_value(sb), "w"); if (op == NULL) die("cannot execute '%s'.", strbuf_value(sb)); gp = gfind_open(dbpath, NULL, GPATH_BOTH); while ((path = gfind_read(gp)) != NULL) { fputs(path, op); fputc('\0', op); } gfind_close(gp); if (pclose(op) != 0) die("terminated abnormally '%s' (errno = %d).", strbuf_value(sb), errno); if (test("f", makepath(dbpath, "ID", NULL))) if (chmod(makepath(dbpath, "ID", NULL), 0644) < 0) die("cannot chmod ID file."); statistics_time_end(tim); } if (vflag) fprintf(stderr, "[%s] Done.\n", now()); closeconf(); strbuf_close(sb); print_statistics(statistics); return 0; }