|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
Copyright(C) 2016, Red Hat, Inc., Stanislav Kozina
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
This program is free software: you can redistribute it and/or modify
|
|
Packit |
400c17 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
400c17 |
the Free Software Foundation, either version 3 of the License, or
|
|
Packit |
400c17 |
(at your option) any later version.
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
400c17 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
400c17 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
400c17 |
GNU General Public License for more details.
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
You should have received a copy of the GNU General Public License
|
|
Packit |
400c17 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
400c17 |
*/
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* This file contains couple of generally useful functions.
|
|
Packit |
400c17 |
*/
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
#include <sys/types.h>
|
|
Packit |
400c17 |
#include <stdlib.h>
|
|
Packit |
400c17 |
#include <stdbool.h>
|
|
Packit |
400c17 |
#include <stdio.h>
|
|
Packit |
400c17 |
#include <errno.h>
|
|
Packit |
400c17 |
#include <string.h>
|
|
Packit |
400c17 |
#include <sys/stat.h>
|
|
Packit |
400c17 |
#include <unistd.h>
|
|
Packit |
400c17 |
#include <dirent.h>
|
|
Packit |
400c17 |
#include <assert.h>
|
|
Packit |
400c17 |
#include <libgen.h> /* dirname() */
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
#include "main.h"
|
|
Packit |
400c17 |
#include "utils.h"
|
|
Packit Service |
28f424 |
#include "hash.h"
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* Sort function for scandir.
|
|
Packit |
400c17 |
* Walk regular file first, then process subdirectories.
|
|
Packit |
400c17 |
*/
|
|
Packit |
400c17 |
int reg_first(const struct dirent **a, const struct dirent **b)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
if ((*a)->d_type == DT_REG && (*b)->d_type != DT_REG)
|
|
Packit |
400c17 |
return -1;
|
|
Packit |
400c17 |
if ((*b)->d_type == DT_REG && (*a)->d_type != DT_REG)
|
|
Packit |
400c17 |
return 1;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* Backup to default collation
|
|
Packit |
400c17 |
* Note: the behavior depends on LC_COLLATE
|
|
Packit |
400c17 |
*/
|
|
Packit |
400c17 |
return alphasort(a, b);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* Call cb() on all nodes in the directory structure @path.
|
|
Packit |
400c17 |
* If list_dirs == true run cb() on subdirectories as well, otherwise list only
|
|
Packit |
400c17 |
* files.
|
|
Packit |
400c17 |
* The cb() has to return true if we continue directory walk or false if we're
|
|
Packit |
400c17 |
* all done.
|
|
Packit |
400c17 |
*/
|
|
Packit |
400c17 |
void walk_dir(char *path, bool list_dirs, walk_rv_t (*cb)(char *, void *),
|
|
Packit |
400c17 |
void *arg)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
struct dirent **entlist;
|
|
Packit |
400c17 |
walk_rv_t cb_rv = WALK_CONT;
|
|
Packit |
400c17 |
int entries, i;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
assert(path != NULL && strlen(path) >= 1);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
entries = scandir(path, &entlist, NULL, reg_first);
|
|
Packit |
400c17 |
if (entries == -1) {
|
|
Packit |
400c17 |
fail("Failed to scan module directory %s: %s\n", path,
|
|
Packit |
400c17 |
strerror(errno));
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* process all the files and directories within directory */
|
|
Packit |
400c17 |
for (i = 0; i < entries; i++) {
|
|
Packit |
400c17 |
struct dirent *ent = entlist[i];
|
|
Packit |
400c17 |
struct stat entstat;
|
|
Packit |
400c17 |
char *new_path;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if ((strcmp(ent->d_name, "..") == 0) ||
|
|
Packit |
400c17 |
(strcmp(ent->d_name, ".") == 0)) {
|
|
Packit |
400c17 |
free(ent);
|
|
Packit |
400c17 |
continue;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (path[strlen(path) - 1] == '/')
|
|
Packit |
400c17 |
safe_asprintf(&new_path, "%s%s", path, ent->d_name);
|
|
Packit |
400c17 |
else
|
|
Packit |
400c17 |
safe_asprintf(&new_path, "%s/%s", path, ent->d_name);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (lstat(new_path, &entstat) != 0) {
|
|
Packit |
400c17 |
fail("Failed to stat directory %s: %s\n", new_path,
|
|
Packit |
400c17 |
strerror(errno));
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (S_ISDIR(entstat.st_mode)) {
|
|
Packit |
400c17 |
if (list_dirs) {
|
|
Packit |
400c17 |
cb_rv = cb(new_path, arg);
|
|
Packit |
400c17 |
if (cb_rv != WALK_CONT)
|
|
Packit |
400c17 |
goto out;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* Ignore symlinks */
|
|
Packit |
400c17 |
if (!S_ISLNK(entstat.st_mode))
|
|
Packit |
400c17 |
walk_dir(new_path, list_dirs, cb, arg);
|
|
Packit |
400c17 |
} else if (S_ISREG(entstat.st_mode)) {
|
|
Packit |
400c17 |
cb_rv = cb(new_path, arg);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
out:
|
|
Packit |
400c17 |
free(new_path);
|
|
Packit |
400c17 |
free(ent);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (cb_rv == WALK_STOP)
|
|
Packit |
400c17 |
break;
|
|
Packit |
400c17 |
if (cb_rv == WALK_SKIP) {
|
|
Packit |
400c17 |
cb_rv = WALK_CONT;
|
|
Packit |
400c17 |
break;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
free(entlist);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
int check_is_directory(char *dir)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
struct stat dirstat;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (stat(dir, &dirstat) != 0)
|
|
Packit |
400c17 |
return errno;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (!S_ISDIR(dirstat.st_mode))
|
|
Packit |
400c17 |
return ENOTDIR;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
return 0;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void safe_mkdir(char *path)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0)
|
|
Packit |
400c17 |
fail("%s", strerror(errno));
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
void rec_mkdir(char *path)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char *buf;
|
|
Packit |
400c17 |
char *pos;
|
|
Packit |
400c17 |
size_t len = strlen(path);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
assert(path != NULL && len > 0);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
buf = safe_strdup(path);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* Get rid of trailing slashes */
|
|
Packit |
400c17 |
for (pos = buf + len - 1; pos > buf && *pos == '/'; --pos)
|
|
Packit |
400c17 |
*pos = '\0';
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
pos = buf;
|
|
Packit |
400c17 |
while (pos != NULL) {
|
|
Packit |
400c17 |
int rv;
|
|
Packit |
400c17 |
char *next;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* Skip multiple slashes */
|
|
Packit |
400c17 |
for (next = pos + 1; *next == '/'; next++)
|
|
Packit |
400c17 |
;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
pos = strchr(next, '/');
|
|
Packit |
400c17 |
if (pos != NULL)
|
|
Packit |
400c17 |
*pos = '\0';
|
|
Packit |
400c17 |
rv = check_is_directory(buf);
|
|
Packit |
400c17 |
if (rv != 0) {
|
|
Packit |
400c17 |
if (rv == ENOENT)
|
|
Packit |
400c17 |
safe_mkdir(buf);
|
|
Packit |
400c17 |
else
|
|
Packit |
400c17 |
fail("%s", strerror(rv));
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (pos != NULL)
|
|
Packit |
400c17 |
*pos = '/';
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
free(buf);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
void safe_rename(const char *oldpath, const char *newpath)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char *temp;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
temp = safe_strdup(newpath);
|
|
Packit |
400c17 |
/* dirname() modifies its buffer! */
|
|
Packit |
400c17 |
rec_mkdir(dirname(temp));
|
|
Packit |
400c17 |
free(temp);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (rename(oldpath, newpath) != 0)
|
|
Packit |
400c17 |
fail("rename() failed: %s\n", strerror(errno));
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
struct norm_ctx {
|
|
Packit |
400c17 |
char *path;
|
|
Packit |
400c17 |
char *p;
|
|
Packit |
400c17 |
char *outp;
|
|
Packit |
400c17 |
};
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* actually, second last, skip the whole directory */
|
|
Packit |
400c17 |
static char *last_slash(char *str, char *end)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = '/';
|
|
Packit |
400c17 |
int met = 0;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
for (; end > str; end--) {
|
|
Packit |
400c17 |
if (*end == c) {
|
|
Packit |
400c17 |
if (met)
|
|
Packit |
400c17 |
return end;
|
|
Packit |
400c17 |
else
|
|
Packit |
400c17 |
met = 1;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return NULL;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
typedef void *(*state_t)(struct norm_ctx *);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *initial(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
static void *normal(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
static void *one_dot(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
static void *two_dots(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
static void *slash(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
static void *end(struct norm_ctx *ctx);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *initial(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = *ctx->p++;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
switch (c) {
|
|
Packit |
400c17 |
case '\0':
|
|
Packit |
400c17 |
*ctx->outp = c;
|
|
Packit |
400c17 |
return end;
|
|
Packit |
400c17 |
case '/':
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
return slash;
|
|
Packit |
400c17 |
case '.':
|
|
Packit |
400c17 |
return one_dot;
|
|
Packit |
400c17 |
default:
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *normal(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = *ctx->p++;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
switch (c) {
|
|
Packit |
400c17 |
case '\0':
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
return end;
|
|
Packit |
400c17 |
case '/':
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
return slash;
|
|
Packit |
400c17 |
default:
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *slash(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = *ctx->p++;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
switch (c) {
|
|
Packit |
400c17 |
case '\0':
|
|
Packit |
400c17 |
fail("Cannot normalize path %s", ctx->path);
|
|
Packit |
400c17 |
case '/':
|
|
Packit |
400c17 |
return slash;
|
|
Packit |
400c17 |
case '.':
|
|
Packit |
400c17 |
return one_dot;
|
|
Packit |
400c17 |
default:
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *one_dot(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = *ctx->p++;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
switch (c) {
|
|
Packit |
400c17 |
case '\0':
|
|
Packit |
400c17 |
*--ctx->outp = c;
|
|
Packit |
400c17 |
return end;
|
|
Packit |
400c17 |
case '/':
|
|
Packit |
400c17 |
return slash;
|
|
Packit |
400c17 |
case '.':
|
|
Packit |
400c17 |
return two_dots;
|
|
Packit |
400c17 |
default:
|
|
Packit |
400c17 |
*ctx->outp++ = '.';
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *two_dots(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char c = *ctx->p++;
|
|
Packit |
400c17 |
char *p;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
switch (c) {
|
|
Packit |
400c17 |
case '\0':
|
|
Packit |
400c17 |
p = last_slash(ctx->path, ctx->outp);
|
|
Packit |
400c17 |
if (p == NULL)
|
|
Packit |
400c17 |
p = ctx->path;
|
|
Packit |
400c17 |
*p = c;
|
|
Packit |
400c17 |
return end;
|
|
Packit |
400c17 |
case '/':
|
|
Packit |
400c17 |
p = last_slash(ctx->path, ctx->outp);
|
|
Packit |
400c17 |
if (p == NULL) {
|
|
Packit |
400c17 |
ctx->outp = ctx->path;
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
ctx->outp = ++p;
|
|
Packit |
400c17 |
return slash;
|
|
Packit |
400c17 |
default:
|
|
Packit |
400c17 |
*ctx->outp++ = '.';
|
|
Packit |
400c17 |
*ctx->outp++ = '.';
|
|
Packit |
400c17 |
*ctx->outp++ = c;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
return normal;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
static void *end(struct norm_ctx *ctx)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
fail("Cannot normalize path %s", ctx->path);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
char *path_normalize(char *path)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
struct norm_ctx ctx = {
|
|
Packit |
400c17 |
.path = path,
|
|
Packit |
400c17 |
.p = path,
|
|
Packit |
400c17 |
.outp = path,
|
|
Packit |
400c17 |
};
|
|
Packit |
400c17 |
state_t state = initial;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
while (state != end)
|
|
Packit |
400c17 |
state = state(&ctx;;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
return path;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/* Removes the two dashes at the end of the prefix */
|
|
Packit |
400c17 |
#define IS_PREFIX(s, prefix) !strncmp(s, prefix, strlen(prefix) - 2)
|
|
Packit |
400c17 |
|
|
Packit Service |
28f424 |
static void split_filename(const char *filename, char **prefix,
|
|
Packit |
400c17 |
char **name, int *version)
|
|
Packit |
400c17 |
{
|
|
Packit Service |
28f424 |
/* GNU version of basename never modifies its argument */
|
|
Packit Service |
28f424 |
char *base = basename((char *)filename);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
version = 0;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if ((sscanf(base, "%m[a-z]--%m[^.-].txt", prefix, name) != 2) &&
|
|
Packit |
400c17 |
(sscanf(base, "%m[a-z]--%m[^.-]-%i.txt",
|
|
Packit |
400c17 |
prefix, name, version) != 3))
|
|
Packit |
400c17 |
fail("Unexpected file name: %s\n", filename);
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* Get the type of a symbol from the name of the kabi file
|
|
Packit |
400c17 |
*
|
|
Packit |
400c17 |
* It allocates the string which must be freed by the caller.
|
|
Packit |
400c17 |
*/
|
|
Packit Service |
28f424 |
char *filenametotype(const char *filename)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char *prefix = NULL, *name = NULL, *type = NULL;
|
|
Packit |
400c17 |
int version = 0;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
split_filename(filename, &prefix, &name, &version);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
if (IS_PREFIX(prefix, TYPEDEF_FILE))
|
|
Packit |
400c17 |
type = name;
|
|
Packit |
400c17 |
else if (IS_PREFIX(prefix, STRUCT_FILE) ||
|
|
Packit |
400c17 |
IS_PREFIX(prefix, UNION_FILE) ||
|
|
Packit |
400c17 |
IS_PREFIX(prefix, ENUM_FILE))
|
|
Packit |
400c17 |
safe_asprintf(&type, "%s %s", prefix, name);
|
|
Packit |
400c17 |
else
|
|
Packit |
400c17 |
fail("Unexpected file prefix: %s\n", prefix);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
free(prefix);
|
|
Packit |
400c17 |
if (name != type)
|
|
Packit |
400c17 |
free(name);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
return type;
|
|
Packit |
400c17 |
}
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
/*
|
|
Packit |
400c17 |
* Get the name of a symbol from the name of the kabi file
|
|
Packit |
400c17 |
*
|
|
Packit |
400c17 |
* It allocates the string which must be freed by the caller.
|
|
Packit |
400c17 |
*/
|
|
Packit Service |
28f424 |
char *filenametosymbol(const char *filename)
|
|
Packit |
400c17 |
{
|
|
Packit |
400c17 |
char *prefix = NULL, *name = NULL;
|
|
Packit |
400c17 |
int version = 0;
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
split_filename(filename, &prefix, &name, &version);
|
|
Packit |
400c17 |
free(prefix);
|
|
Packit |
400c17 |
|
|
Packit |
400c17 |
return name;
|
|
Packit |
400c17 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
struct hash *global_string_keeper;
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
void global_string_keeper_init(void)
|
|
Packit Service |
28f424 |
{
|
|
Packit Service |
28f424 |
global_string_keeper = hash_new(1 << 20, free);
|
|
Packit Service |
28f424 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
void global_string_keeper_free(void)
|
|
Packit Service |
28f424 |
{
|
|
Packit Service |
28f424 |
hash_free(global_string_keeper);
|
|
Packit Service |
28f424 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
const char *global_string_get_copy(const char *string)
|
|
Packit Service |
28f424 |
{
|
|
Packit Service |
28f424 |
const char *result;
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
if (string == NULL)
|
|
Packit Service |
28f424 |
return NULL;
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
result = hash_find(global_string_keeper, string);
|
|
Packit Service |
28f424 |
if (result == NULL) {
|
|
Packit Service |
28f424 |
result = safe_strdup(string);
|
|
Packit Service |
28f424 |
hash_add(global_string_keeper, result, result);
|
|
Packit Service |
28f424 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
return result;
|
|
Packit Service |
28f424 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
const char *global_string_get_move(char *string)
|
|
Packit Service |
28f424 |
{
|
|
Packit Service |
28f424 |
const char *result;
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
if (string == NULL)
|
|
Packit Service |
28f424 |
return NULL;
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
result = hash_find(global_string_keeper, string);
|
|
Packit Service |
28f424 |
if (result == NULL) {
|
|
Packit Service |
28f424 |
result = string;
|
|
Packit Service |
28f424 |
hash_add(global_string_keeper, result, result);
|
|
Packit Service |
28f424 |
} else {
|
|
Packit Service |
28f424 |
free(string);
|
|
Packit Service |
28f424 |
}
|
|
Packit Service |
28f424 |
|
|
Packit Service |
28f424 |
return result;
|
|
Packit Service |
28f424 |
}
|