1/*
2 * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2007 Lawrence Livermore National Lab
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 *     Redistribution and use in source and binary forms, with or
12 *     without modification, are permitted provided that the following
13 *     conditions are met:
14 *
15 *      - Redistributions of source code must retain the above
16 *        copyright notice, this list of conditions and the following
17 *        disclaimer.
18 *
19 *      - Redistributions in binary form must reproduce the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer in the documentation and/or other materials
22 *        provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 *
33 */
34
35#define _GNU_SOURCE
36#include <stdio.h>
37#include <errno.h>
38#include <string.h>
39#include <stdlib.h>
40#include <stdarg.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <unistd.h>
44#include <ctype.h>
45#include <config.h>
46#include <errno.h>
47
48#include <complib/cl_nodenamemap.h>
49#include <complib/cl_math.h>
50
51#define PARSE_NODE_MAP_BUFLEN  256
52
53static int parse_node_map_wrap(const char *file_name,
54			       int (*create)(void *, uint64_t, char *),
55			       void *cxt,
56			       char *linebuf,
57			       unsigned int linebuflen);
58
59static int map_name(void *cxt, uint64_t guid, char *p)
60{
61	cl_qmap_t *map = cxt;
62	name_map_item_t *item;
63
64	p = strtok(p, "\"#");
65	if (!p)
66		return 0;
67
68	item = malloc(sizeof(*item));
69	if (!item)
70		return -1;
71	item->guid = guid;
72	item->name = strdup(p);
73	cl_qmap_insert(map, item->guid, (cl_map_item_t *) item);
74	return 0;
75}
76
77nn_map_t *open_node_name_map(const char *node_name_map)
78{
79	nn_map_t *map;
80	char linebuf[PARSE_NODE_MAP_BUFLEN + 1];
81
82	if (!node_name_map) {
83#ifdef HAVE_DEFAULT_NODENAME_MAP
84		struct stat buf;
85		node_name_map = HAVE_DEFAULT_NODENAME_MAP;
86		if (stat(node_name_map, &buf))
87			return NULL;
88#else
89		return NULL;
90#endif				/* HAVE_DEFAULT_NODENAME_MAP */
91	}
92
93	map = malloc(sizeof(*map));
94	if (!map)
95		return NULL;
96	cl_qmap_init(map);
97
98	memset(linebuf, '\0', PARSE_NODE_MAP_BUFLEN + 1);
99	if (parse_node_map_wrap(node_name_map, map_name, map,
100				linebuf, PARSE_NODE_MAP_BUFLEN)) {
101		if (errno == EIO) {
102			fprintf(stderr,
103				"WARNING failed to parse node name map "
104				"\"%s\"\n",
105				node_name_map);
106			fprintf(stderr,
107				"WARNING failed line: \"%s\"\n",
108				linebuf);
109		}
110		else
111			fprintf(stderr,
112				"WARNING failed to open node name map "
113				"\"%s\" (%s)\n",
114				node_name_map, strerror(errno));
115		close_node_name_map(map);
116		return NULL;
117	}
118
119	return map;
120}
121
122void close_node_name_map(nn_map_t * map)
123{
124	name_map_item_t *item = NULL;
125
126	if (!map)
127		return;
128
129	item = (name_map_item_t *) cl_qmap_head(map);
130	while (item != (name_map_item_t *) cl_qmap_end(map)) {
131		item = (name_map_item_t *) cl_qmap_remove(map, item->guid);
132		free(item->name);
133		free(item);
134		item = (name_map_item_t *) cl_qmap_head(map);
135	}
136	free(map);
137}
138
139char *remap_node_name(nn_map_t * map, uint64_t target_guid, char *nodedesc)
140{
141	char *rc = NULL;
142	name_map_item_t *item = NULL;
143
144	if (!map)
145		goto done;
146
147	item = (name_map_item_t *) cl_qmap_get(map, target_guid);
148	if (item != (name_map_item_t *) cl_qmap_end(map))
149		rc = strdup(item->name);
150
151done:
152	if (rc == NULL)
153		rc = strdup(clean_nodedesc(nodedesc));
154	return (rc);
155}
156
157char *clean_nodedesc(char *nodedesc)
158{
159	int i = 0;
160
161	nodedesc[63] = '\0';
162	while (nodedesc[i]) {
163		if (!isprint(nodedesc[i]))
164			nodedesc[i] = ' ';
165		i++;
166	}
167
168	return (nodedesc);
169}
170
171static int parse_node_map_wrap(const char *file_name,
172			       int (*create) (void *, uint64_t, char *),
173			       void *cxt,
174			       char *linebuf,
175			       unsigned int linebuflen)
176{
177	char line[PARSE_NODE_MAP_BUFLEN];
178	FILE *f;
179
180	if (!(f = fopen(file_name, "r")))
181		return -1;
182
183	while (fgets(line, sizeof(line), f)) {
184		uint64_t guid;
185		char *p, *e;
186
187		p = line;
188		while (isspace(*p))
189			p++;
190		if (*p == '\0' || *p == '\n' || *p == '#')
191			continue;
192
193		guid = strtoull(p, &e, 0);
194		if (e == p || (!isspace(*e) && *e != '#' && *e != '\0')) {
195			fclose(f);
196			errno = EIO;
197			if (linebuf) {
198				memcpy(linebuf, line,
199				       MIN(PARSE_NODE_MAP_BUFLEN, linebuflen));
200				e = strpbrk(linebuf, "\n");
201				if (e)
202					*e = '\0';
203			}
204			return -1;
205		}
206
207		p = e;
208		while (isspace(*p))
209			p++;
210
211		e = strpbrk(p, "\n");
212		if (e)
213			*e = '\0';
214
215		if (create(cxt, guid, p)) {
216			fclose(f);
217			return -1;
218		}
219	}
220
221	fclose(f);
222	return 0;
223}
224
225int parse_node_map(const char *file_name,
226		   int (*create) (void *, uint64_t, char *), void *cxt)
227{
228	return parse_node_map_wrap(file_name, create, cxt, NULL, 0);
229}
230