mirror of
git://nv-tegra.nvidia.com/tegra/gfx-src/nv-xconfig.git
synced 2025-12-22 09:22:53 +03:00
Updating prebuilts and/or headers
6f6f68f976250f2646450e571f9ab2d7eee1ac80 - nvidia-xconfig-540.2.0/nvidia-cfg.h 46f2ea329459b0b16cb36cc14cec0de737d0963e - nvidia-xconfig-540.2.0/options.c 9b0c02164398be2795fea7cb13c9e1b062d24bfb - nvidia-xconfig-540.2.0/query_gpu_info.c b1bc157844c5570f911b2bf45249bd26ce73efef - nvidia-xconfig-540.2.0/Makefile 10edc2c301fd331439b38d001c0df41669c238b2 - nvidia-xconfig-540.2.0/multiple_screens.c f14e9577e537037d4778d490ef70f13b0e94a70a - nvidia-xconfig-540.2.0/option_table.h 1e39095238886dfc6a69f7ec750e10c05a93e7d1 - nvidia-xconfig-540.2.0/nvidia-xconfig.1.m4 913b088cb559f31e09a1baf89d85d75cb43079b4 - nvidia-xconfig-540.2.0/nvidia-xconfig.h 647e7896275a1113ec99352d573823a05001f57e - nvidia-xconfig-540.2.0/lscf.c bfa37f78ba458f14a1865bbf3f67eb84987a7e1c - nvidia-xconfig-540.2.0/extract_edids.c 41bcac41393c9a465c30c07cf1ab386647a16687 - nvidia-xconfig-540.2.0/util.c a5ad539267b73169480e7898b284823639c4db3a - nvidia-xconfig-540.2.0/tree.c 4cc77b90af91e615a64ae04893fdffa7939db84c - nvidia-xconfig-540.2.0/COPYING c946eefad99cec9366d8abbd4e45c5d138d3b7be - nvidia-xconfig-540.2.0/make_usable.c d37da5a118e0418b267a48d05fd144611316b42c - nvidia-xconfig-540.2.0/gen-manpage-opts.c b3d0f9f27c4d9cb7940d04e1dd387d357a16024c - nvidia-xconfig-540.2.0/nvidia-xconfig.c 524990f5497f9bbeb3d148b5e7dc8d2267c3163d - nvidia-xconfig-540.2.0/common-utils/nvpci-utils.c abb5c1b445d9353f2d2840bda848cd16109710a4 - nvidia-xconfig-540.2.0/common-utils/msg.h 1654638c567bc7f2bd70b54d807b498ab14c1061 - nvidia-xconfig-540.2.0/common-utils/nvpci-utils.h 8a346196b052cfb1e06dd83d2ad1fe71e928d2b3 - nvidia-xconfig-540.2.0/common-utils/common-utils.c e572cac43202f6c2af1c80b9e3901215126093ed - nvidia-xconfig-540.2.0/common-utils/nvgetopt.h 8db48a58d1654ed69920366bef10f38b789a1a84 - nvidia-xconfig-540.2.0/common-utils/msg.c 8259a24058c714629f9819cc8c830ea9b202bb27 - nvidia-xconfig-540.2.0/common-utils/gen-manpage-opts-helper.h 5d55b94375c2055cfa1578e4c7f34c90e63a33f7 - nvidia-xconfig-540.2.0/common-utils/gen-manpage-opts-helper.c dc2678d8a9d794a4b2b2718fce57ec087f21f54b - nvidia-xconfig-540.2.0/common-utils/common-utils.h 384e36102dcd08ed4c5de05b5e3b8a7cdb2e257d - nvidia-xconfig-540.2.0/common-utils/nvgetopt.c 33211ca0a10f50e2c87b9e8feef6c1ab381b57a1 - nvidia-xconfig-540.2.0/XF86Config-parser/DRI.c 5ffb2caa5077a2e6ec1c5ece807e71503fb2fbce - nvidia-xconfig-540.2.0/XF86Config-parser/Module.c 953b945f3b117d6fb44f1f738af17b6380a9ec72 - nvidia-xconfig-540.2.0/XF86Config-parser/Monitor.c de1c758e29f217e1a99e4c076d54ac84bce98b18 - nvidia-xconfig-540.2.0/XF86Config-parser/Screen.c f3d611bdbddfa64675a0810ef81dada57e224bcd - nvidia-xconfig-540.2.0/XF86Config-parser/Extensions.c ec19d673a6a7d1d8f855f2d32d3e8f63046c3625 - nvidia-xconfig-540.2.0/XF86Config-parser/Files.c e67d630ef396ab7d34524c333f3a77fc42ba8fc6 - nvidia-xconfig-540.2.0/XF86Config-parser/configProcs.h c66a0a141e25e31b568fb9df41f17d7fb9e6d3b9 - nvidia-xconfig-540.2.0/XF86Config-parser/xf86Parser.h 4d9b03ea3badceb6bdfdf6589e6731140ec44079 - nvidia-xconfig-540.2.0/XF86Config-parser/Generate.c cda3a4ab05bf48ba28af35b5c4c632e968afc7fa - nvidia-xconfig-540.2.0/XF86Config-parser/Util.c 83b0a8efd6a508db54995688ab353591bdb242a2 - nvidia-xconfig-540.2.0/XF86Config-parser/Flags.c 45ceb0129668346ae3e52d81bb6e2f97efadf9d0 - nvidia-xconfig-540.2.0/XF86Config-parser/Input.c 18711ff932af2202869a30f3b32d6d7fe7811c84 - nvidia-xconfig-540.2.0/XF86Config-parser/Layout.c c7b8d8ca0f7c9dcc2cdca4f8e77d1122c71892ef - nvidia-xconfig-540.2.0/XF86Config-parser/Read.c 0a274c4bc54b6ae0f6d009e443bda0cb033d66b5 - nvidia-xconfig-540.2.0/XF86Config-parser/Pointer.c 04efe162cf6d97882f2bb87f3712d9a65c2320f3 - nvidia-xconfig-540.2.0/XF86Config-parser/Scan.c 7344be997921dec57959691e986763ee686888d5 - nvidia-xconfig-540.2.0/XF86Config-parser/Device.c 4407207cf890539dc604cff5b834c994b307729a - nvidia-xconfig-540.2.0/XF86Config-parser/Write.c 3f2238c88d737bd329a9bca1ac4b0bcf77bb9ac2 - nvidia-xconfig-540.2.0/XF86Config-parser/xf86tokens.h a9bc06f33bf525c2b08be2dc3cd64a59c4c7946d - nvidia-xconfig-540.2.0/XF86Config-parser/Configint.h 9cbc29da282aa957f28b7fc83caf1e3b19ee2a52 - nvidia-xconfig-540.2.0/XF86Config-parser/Vendor.c 2022a4a3c2a1b23a67ae74f50a3849f5f3a45e4b - nvidia-xconfig-540.2.0/XF86Config-parser/Keyboard.c 6c210ad0eaee1db3fec48ff01746cb054b4f9aaa - nvidia-xconfig-540.2.0/XF86Config-parser/Video.c ac878b26ded86a3c502a6a81fc4c4a96162afefb - nvidia-xconfig-540.2.0/XF86Config-parser/Merge.c Change-Id: Id3a1ed94e65b037e298685f026d5630e5039e5a4
This commit is contained in:
826
nvidia-xconfig-540.2.0/common-utils/common-utils.c
Normal file
826
nvidia-xconfig-540.2.0/common-utils/common-utils.c
Normal file
@@ -0,0 +1,826 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2012 NVIDIA Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "common-utils.h"
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Memory allocation helper functions */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* nvalloc() - calloc wrapper that checks for errors; if an error
|
||||
* occurs, an error is printed to stderr and exit is called -- this
|
||||
* function will only return on success.
|
||||
*/
|
||||
|
||||
void *nvalloc(size_t size)
|
||||
{
|
||||
void *m = calloc(1, size);
|
||||
|
||||
if (!m) {
|
||||
fprintf(stderr, "%s: memory allocation failure (%s)! \n",
|
||||
PROGRAM_NAME, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return m;
|
||||
|
||||
} /* nvalloc() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvstrcat() - allocate a new string, copying all given strings
|
||||
* into it.
|
||||
*/
|
||||
|
||||
char *nvstrcat(const char *str, ...)
|
||||
{
|
||||
const char *s;
|
||||
char *result;
|
||||
size_t len;
|
||||
va_list ap;
|
||||
|
||||
/* walk the varargs to compute the length of the result string */
|
||||
|
||||
va_start(ap, str);
|
||||
|
||||
for (s = str, len = 1; s; s = va_arg(ap, char *)) {
|
||||
len += strlen(s);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
/* allocate the result string */
|
||||
|
||||
result = nvalloc(len);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
result[0] = '\0';
|
||||
|
||||
/* concatenate the input strings, writing into the result string */
|
||||
|
||||
va_start(ap, str);
|
||||
|
||||
for (s = str; s; s = va_arg(ap, char *)) {
|
||||
strcat(result, s);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return result;
|
||||
} /* nvstrcat() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvrealloc() - realloc wrapper that checks for errors; if an error
|
||||
* occurs, an error is printed to stderr and exit is called -- this
|
||||
* function will only return on success.
|
||||
*/
|
||||
|
||||
void *nvrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *m;
|
||||
|
||||
if (ptr == NULL) return nvalloc(size);
|
||||
|
||||
m = realloc(ptr, size);
|
||||
if (!m) {
|
||||
fprintf(stderr, "%s: memory re-allocation failure (%s)! \n",
|
||||
PROGRAM_NAME, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return m;
|
||||
|
||||
} /* nvrealloc() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvstrdup() - wrapper for strdup() that checks the return value; if
|
||||
* an error occurs, an error is printed to stderr and exit is called
|
||||
* -- this function will only return on success.
|
||||
*/
|
||||
|
||||
char *nvstrdup(const char *s)
|
||||
{
|
||||
char *m;
|
||||
|
||||
if (!s) return NULL;
|
||||
|
||||
m = strdup(s);
|
||||
|
||||
if (!m) {
|
||||
fprintf(stderr, "%s: memory allocation failure during strdup (%s)! \n",
|
||||
PROGRAM_NAME, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return m;
|
||||
|
||||
} /* nvstrdup() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvstrndup() - implementation of strndup() that checks return values; if
|
||||
* an error occurs, an error is printed to stderr and exit is called
|
||||
* -- this function will only return on success.
|
||||
*/
|
||||
|
||||
char *nvstrndup(const char *s, size_t n)
|
||||
{
|
||||
char *m;
|
||||
|
||||
if (!s) return NULL;
|
||||
|
||||
m = malloc(n + 1);
|
||||
|
||||
if (!m) {
|
||||
fprintf(stderr, "%s: memory allocation failure during malloc (%s)! \n",
|
||||
PROGRAM_NAME, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strncpy (m, s, n);
|
||||
m[n] = '\0';
|
||||
|
||||
return m;
|
||||
|
||||
} /* nvstrndup() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvstrtolower() - convert the given string to lowercase.
|
||||
*/
|
||||
|
||||
char *nvstrtolower(char *s)
|
||||
{
|
||||
char *start = s;
|
||||
|
||||
if (s == NULL) return NULL;
|
||||
|
||||
while (*s) {
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return start;
|
||||
|
||||
} /* nvstrtolower() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvstrtoupper() - convert the given string to uppercase.
|
||||
*/
|
||||
|
||||
char *nvstrtoupper(char *s)
|
||||
{
|
||||
char *start = s;
|
||||
|
||||
if (s == NULL) return NULL;
|
||||
|
||||
while (*s) {
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return start;
|
||||
|
||||
} /* nvstrtoupper() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvasprintf() - implementation of asprintf() that checks return values; if an
|
||||
* error occurs, an error is printed to stderr and exit is called.
|
||||
* -- this function will only return on success.
|
||||
*/
|
||||
char *nvasprintf(const char *fmt, ...)
|
||||
{
|
||||
char *str;
|
||||
|
||||
NV_VSNPRINTF(str, fmt);
|
||||
|
||||
return str;
|
||||
|
||||
} /* nvasprintf() */
|
||||
|
||||
/*
|
||||
* nv_append_sprintf() - similar to glib's g_string_append_printf(), except
|
||||
* instead of operating on a GString it operates on a (char **). Appends a
|
||||
* formatted string to the end of the dynamically-allocated string pointed to by
|
||||
* *buf (or the empty string if *buf is NULL), potentially reallocating the
|
||||
* string in the process. This function only returns on success.
|
||||
*/
|
||||
void nv_append_sprintf(char **buf, const char *fmt, ...)
|
||||
{
|
||||
char *prefix, *suffix;
|
||||
|
||||
prefix = *buf;
|
||||
NV_VSNPRINTF(suffix, fmt);
|
||||
|
||||
if (!prefix) {
|
||||
*buf = suffix;
|
||||
} else {
|
||||
*buf = nvstrcat(prefix, suffix, NULL);
|
||||
free(prefix);
|
||||
free(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* nvfree() - frees memory allocated with nvalloc(), provided
|
||||
* a non-NULL pointer is provided.
|
||||
*/
|
||||
void nvfree(void *s)
|
||||
{
|
||||
if (s) free(s);
|
||||
|
||||
} /* nvfree() */
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* misc */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* tilde_expansion() - do tilde expansion on the given path name;
|
||||
* based loosely on code snippets found in the comp.unix.programmer
|
||||
* FAQ. The tilde expansion rule is: if a tilde ('~') is alone or
|
||||
* followed by a '/', then substitute the current user's home
|
||||
* directory; if followed by the name of a user, then substitute that
|
||||
* user's home directory.
|
||||
*
|
||||
* Returns NULL if its argument is NULL; otherwise, returns a malloced
|
||||
* and tilde-expanded string.
|
||||
*/
|
||||
|
||||
char *tilde_expansion(const char *str)
|
||||
{
|
||||
char *prefix = NULL;
|
||||
const char *replace;
|
||||
char *user, *ret;
|
||||
struct passwd *pw;
|
||||
int len;
|
||||
|
||||
if (!str) return NULL;
|
||||
|
||||
if (str[0] != '~') return strdup(str);
|
||||
|
||||
if ((str[1] == '/') || (str[1] == '\0')) {
|
||||
|
||||
/* expand to the current user's home directory */
|
||||
|
||||
prefix = getenv("HOME");
|
||||
if (!prefix) {
|
||||
|
||||
/* $HOME isn't set; get the home directory from /etc/passwd */
|
||||
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) prefix = pw->pw_dir;
|
||||
}
|
||||
|
||||
replace = str + 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* expand to the specified user's home directory */
|
||||
|
||||
replace = strchr(str, '/');
|
||||
if (!replace) replace = str + strlen(str);
|
||||
|
||||
len = replace - str;
|
||||
user = malloc(len + 1);
|
||||
strncpy(user, str+1, len-1);
|
||||
user[len] = '\0';
|
||||
pw = getpwnam(user);
|
||||
if (pw) prefix = pw->pw_dir;
|
||||
free (user);
|
||||
}
|
||||
|
||||
if (!prefix) return strdup(str);
|
||||
|
||||
ret = malloc(strlen(prefix) + strlen(replace) + 1);
|
||||
strcpy(ret, prefix);
|
||||
strcat(ret, replace);
|
||||
|
||||
return ret;
|
||||
|
||||
} /* tilde_expansion() */
|
||||
|
||||
|
||||
/*
|
||||
* nv_prepend_to_string_list() - add a new string to a string list, delimited
|
||||
* by the given string delimiter. The original list is freed.
|
||||
*/
|
||||
|
||||
char *nv_prepend_to_string_list(char *list, const char *item, const char *delim)
|
||||
{
|
||||
char *new_list = nvstrcat(item, list ? delim : NULL, list, NULL);
|
||||
nvfree(list);
|
||||
return new_list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read from the given FILE stream until a newline, EOF, or nul
|
||||
* terminator is encountered, writing data into a growable buffer.
|
||||
* The eof parameter is set to TRUE when EOF is encountered. In all
|
||||
* cases, the returned string is null-terminated.
|
||||
*
|
||||
* XXX this function will be rather slow because it uses fgetc() to
|
||||
* pull each character off the stream one at a time; this is done so
|
||||
* that each character can be examined as it's read so that we can
|
||||
* appropriately deal with EOFs and newlines. A better implementation
|
||||
* would use fgets(), but that would still require us to parse each
|
||||
* read line, checking for newlines or guessing if we hit an EOF.
|
||||
*/
|
||||
char *fget_next_line(FILE *fp, int *eof)
|
||||
{
|
||||
char *buf = NULL, *tmpbuf;
|
||||
char *c = NULL;
|
||||
int len = 0, buflen = 0;
|
||||
int ret;
|
||||
|
||||
const int __fget_next_line_len = 32;
|
||||
|
||||
if (eof) {
|
||||
*eof = FALSE;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (buflen == len) { /* buffer isn't big enough -- grow it */
|
||||
buflen += __fget_next_line_len;
|
||||
tmpbuf = nvalloc(buflen);
|
||||
if (buf) {
|
||||
memcpy(tmpbuf, buf, len);
|
||||
nvfree(buf);
|
||||
}
|
||||
buf = tmpbuf;
|
||||
c = buf + len;
|
||||
}
|
||||
|
||||
ret = fgetc(fp);
|
||||
|
||||
if ((ret == EOF) && (eof)) {
|
||||
*eof = TRUE;
|
||||
}
|
||||
|
||||
if ((ret == EOF) || (ret == '\n') || (ret == '\0')) {
|
||||
*c = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
*c = (char) ret;
|
||||
|
||||
len++;
|
||||
c++;
|
||||
|
||||
} /* while (1) */
|
||||
|
||||
return NULL; /* should never get here */
|
||||
}
|
||||
|
||||
char *nvstrchrnul(char *s, int c)
|
||||
{
|
||||
char *result = strchr(s, c);
|
||||
if (!result) {
|
||||
return (s + strlen(s));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* file helper functions */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* nv_open() - open(2) wrapper; prints an error message if open(2)
|
||||
* fails and calls exit(). This function only returns on success.
|
||||
*/
|
||||
|
||||
int nv_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
int fd;
|
||||
fd = open(pathname, flags, mode);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Failure opening %s (%s).\n",
|
||||
pathname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return fd;
|
||||
|
||||
} /* nv_name() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_get_file_length() - stat(2) wrapper; prints an error message if
|
||||
* the system call fails and calls exit(). This function only returns
|
||||
* on success.
|
||||
*/
|
||||
|
||||
int nv_get_file_length(const char *filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filename, &stat_buf);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Unable to determine '%s' file length (%s).\n",
|
||||
filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return stat_buf.st_size;
|
||||
|
||||
} /* nv_get_file_length() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_set_file_length() - wrapper for lseek() and write(); prints an
|
||||
* error message if the system calls fail and calls exit(). This
|
||||
* function only returns on success.
|
||||
*/
|
||||
|
||||
void nv_set_file_length(const char *filename, int fd, int len)
|
||||
{
|
||||
if ((lseek(fd, len - 1, SEEK_SET) == -1) ||
|
||||
(write(fd, "", 1) == -1)) {
|
||||
fprintf(stderr, "Unable to set file '%s' length %d (%s).\n",
|
||||
filename, fd, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
} /* nv_set_file_length() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_mmap() - mmap(2) wrapper; prints an error message if mmap(2)
|
||||
* fails and calls exit(). This function only returns on success.
|
||||
*/
|
||||
|
||||
void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
ret = mmap(0, len, prot, flags, fd, 0);
|
||||
if (ret == (void *) -1) {
|
||||
fprintf(stderr, "Unable to mmap file %s (%s).\n",
|
||||
filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return ret;
|
||||
|
||||
} /* nv_mmap() */
|
||||
|
||||
|
||||
/*
|
||||
* nv_basename() - alternative to basename(3) which avoids differences in
|
||||
* behavior from different implementations: this implementation never modifies
|
||||
* the original string, and the return value can always be passed to free(3).
|
||||
*/
|
||||
|
||||
char *nv_basename(const char *path)
|
||||
{
|
||||
char *last_slash = strrchr(path, '/');
|
||||
if (last_slash) {
|
||||
return strdup(last_slash+1);
|
||||
} else {
|
||||
return strdup(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* nv_mkdir_recursive() - make a directory and all parent directories as needed.
|
||||
* dir_list is an optional arguments that if not empty, will be set to a string
|
||||
* containing a newline separated list of all directories created.
|
||||
*/
|
||||
int nv_mkdir_recursive(const char *path, const mode_t mode,
|
||||
char **error_str, char **dir_list)
|
||||
{
|
||||
char *c, *tmp, ch, *list;
|
||||
int success = FALSE;
|
||||
|
||||
if (!path || !path[0]) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tmp = nvstrdup(path);
|
||||
remove_trailing_slashes(tmp);
|
||||
|
||||
list = NULL;
|
||||
|
||||
c = tmp;
|
||||
do {
|
||||
c++;
|
||||
if ((*c == '/') || (*c == '\0')) {
|
||||
ch = *c;
|
||||
*c = '\0';
|
||||
if (!directory_exists(tmp)) {
|
||||
char *tmplist;
|
||||
if (mkdir(tmp, mode) != 0) {
|
||||
*error_str =
|
||||
nvasprintf("Failure creating directory '%s' : (%s)",
|
||||
tmp, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
/* Prepend the created directory path to a running list */
|
||||
if (dir_list) {
|
||||
tmplist = list;
|
||||
list = nvstrcat(tmp, "\n", tmplist, NULL);
|
||||
free(tmplist);
|
||||
}
|
||||
}
|
||||
*c = ch;
|
||||
}
|
||||
} while (*c);
|
||||
|
||||
/* Log any created directories */
|
||||
if (dir_list && list) {
|
||||
*dir_list = list;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
done:
|
||||
|
||||
if (!dir_list) {
|
||||
free(list);
|
||||
}
|
||||
free(tmp);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nvdircat() - concatenate path elements, inserting a '/' path separator
|
||||
* character between each element.
|
||||
*/
|
||||
|
||||
char *nvdircat(const char *str, ...)
|
||||
{
|
||||
const char *s;
|
||||
char *result = nvstrdup("");
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, str);
|
||||
|
||||
for (s = str; s; s = va_arg(ap, char *)) {
|
||||
char *oldresult = result;
|
||||
|
||||
result = nvstrcat(result, s == str ? "" : "/", s, NULL);
|
||||
nvfree(oldresult);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
collapse_multiple_slashes(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dirname(3) workalike that abstracts away implementation-specific behavior:
|
||||
* this function always returns a heap-allocated string that can be passed to
|
||||
* free(3), and never modifies the contents of the original string.
|
||||
*/
|
||||
char *nv_dirname(const char *path)
|
||||
{
|
||||
char *last_slash = strrchr(path, '/');
|
||||
if (last_slash) {
|
||||
return nvstrndup(path, last_slash - path);
|
||||
} else {
|
||||
return nvstrdup(".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Simple helper function to write the contents of a NUL-terminated string to
|
||||
* a file. A trailing newline is appended if not already present.
|
||||
* Returns TRUE on success; FALSE if an error occurred.
|
||||
*/
|
||||
int nv_string_to_file(const char *destination, const char *data)
|
||||
{
|
||||
char *dname = nv_dirname(destination);
|
||||
int written, newline_success = TRUE;
|
||||
char *error = NULL;
|
||||
int len, ret;
|
||||
FILE *fp;
|
||||
|
||||
ret = nv_mkdir_recursive(dname, 0755, &error, NULL);
|
||||
nvfree(dname);
|
||||
nvfree(error);
|
||||
|
||||
if (!ret) return FALSE;
|
||||
|
||||
fp = fopen(destination, "w");
|
||||
if (!fp) return FALSE;
|
||||
|
||||
len = strlen(data);
|
||||
written = fwrite(data, 1, len, fp);
|
||||
if (data[len-1] != '\n') {
|
||||
if (fwrite("\n", 1, 1, fp) != 1) {
|
||||
newline_success = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp)) return FALSE;
|
||||
if (chmod(destination, 0644)) return FALSE;
|
||||
|
||||
return written == len && newline_success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* string helper functions */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* nv_trim_space() - remove any leading and trailing whitespace from a string
|
||||
* and return a pointer to the modified string. The original string may be
|
||||
* modified; the returned value should *NOT* be deallocated with free(), since
|
||||
* it may point somewhere other than the beginning of the original string. If
|
||||
* the original string was a malloc()ed buffer, that string should be stored
|
||||
* separately from the returned value of nv_strip_space, and freed.
|
||||
*/
|
||||
|
||||
char *nv_trim_space(char *string) {
|
||||
char *ret, *end;
|
||||
|
||||
for (ret = string; *ret && isspace(*ret); ret++);
|
||||
for (end = ret + strlen(ret) - 1; end >= ret && isspace(*end); end--) {
|
||||
*end = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* trim_char() - helper function to remove a character from the initial and
|
||||
* final positions of a string, and optionally report how many replacements
|
||||
* were made. The returned value should not be free()d (see nv_trim_space()).
|
||||
*/
|
||||
|
||||
static char *trim_char(char *string, char trim, int *count) {
|
||||
int len, replaced = 0;
|
||||
|
||||
if (count) {
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
if (string == NULL || trim == '\0') {
|
||||
return string;
|
||||
}
|
||||
|
||||
if (string[0] == trim) {
|
||||
string++;
|
||||
replaced++;
|
||||
}
|
||||
|
||||
len = strlen(string);
|
||||
|
||||
if (string[len - 1] == trim) {
|
||||
string[len - 1] = '\0';
|
||||
replaced++;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
*count = replaced;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
* nv_trim_char() - remove a character from the initial and final positions of
|
||||
* a string. The returned value should not be free()d (see nv_trim_space()).
|
||||
*/
|
||||
|
||||
char *nv_trim_char(char *string, char trim) {
|
||||
return trim_char(string, trim, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* nv_trim_char_strict() - remove a character from the initial and final
|
||||
* positions of a string. If no replacements were made, or if replacements were
|
||||
* made at both positions, return the modified string. Otherwise, return NULL.
|
||||
* The returned value should not be free()d (see nv_trim_space()).
|
||||
*/
|
||||
|
||||
char *nv_trim_char_strict(char *string, char trim) {
|
||||
int count;
|
||||
char *trimmed;
|
||||
|
||||
trimmed = trim_char(string, trim, &count);
|
||||
|
||||
if (count == 0 || count == 2) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* directory_exists() - test whether the given directory exists
|
||||
*/
|
||||
|
||||
int directory_exists(const char *dir)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
|
||||
if ((stat (dir, &stat_buf) == -1) || (!S_ISDIR(stat_buf.st_mode))) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_trailing_slashes() - begin at the end of the given string,
|
||||
* and overwrite slashes with NULL as long as we find slashes.
|
||||
*/
|
||||
|
||||
void remove_trailing_slashes(char *string)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (string == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(string);
|
||||
|
||||
while (string[len-1] == '/') {
|
||||
string[--len] = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* collapse_multiple_slashes() - remove any/all occurrences of "//" from the
|
||||
* argument string.
|
||||
*/
|
||||
|
||||
void collapse_multiple_slashes(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = strstr(s, "//")) != NULL) {
|
||||
p++; /* advance to second '/' */
|
||||
while (*p == '/') {
|
||||
unsigned int i, len;
|
||||
|
||||
len = strlen(p);
|
||||
for (i = 0; i < len; i++) p[i] = p[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user