/*
* Copyright (c) 2004-2008 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1983, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
#ifdef _WIN32
# include /* Conflicts */
# include
# include
# include
#else
# include
# include
# include
#endif
#include
#include
#include
int
AG_MkDir(const char *dir)
{
#ifdef _WIN32
if (CreateDirectory(dir, NULL)) {
return (0);
} else {
AG_SetError(_("%s: Failed to create directory (%d)"), dir,
(int)GetLastError());
return (-1);
}
#else
if (mkdir(dir, 0700) == 0) {
return (0);
} else {
AG_SetError(_("%s: Failed to create directory (%s)"), dir,
strerror(errno));
return (-1);
}
#endif
}
int
AG_RmDir(const char *dir)
{
#ifdef _WIN32
if (RemoveDirectory(dir)) {
return (0);
} else {
AG_SetError(_("%s: Failed to remove directory (%d)"), dir,
(int)GetLastError());
return (-1);
}
#else
if (rmdir(dir) == 0) {
return (0);
} else {
AG_SetError(_("%s: Failed to remove directory (%s)"), dir,
strerror(errno));
return (-1);
}
#endif
}
int
AG_ChDir(const char *dir)
{
#ifdef _WIN32
if (SetCurrentDirectory(dir)) {
return (0);
} else {
AG_SetError(_("%s: Failed to change directory (%d)"), dir,
(int)GetLastError());
return (-1);
}
#else
if (chdir(dir) == 0) {
return (0);
} else {
AG_SetError(_("%s: Failed to change directory (%s)"), dir,
strerror(errno));
return (-1);
}
#endif
}
AG_Dir *
AG_OpenDir(const char *path)
{
AG_Dir *dir;
dir = Malloc(sizeof(AG_Dir));
dir->ents = NULL;
dir->nents = 0;
#ifdef _WIN32
{
char dpath[AG_PATHNAME_MAX];
HANDLE h;
WIN32_FIND_DATA fdata;
DWORD rv;
Strlcpy(dpath, path, sizeof(dpath));
Strlcat(dpath, "\\*", sizeof(dpath));
if ((h = FindFirstFile(dpath, &fdata))==INVALID_HANDLE_VALUE) {
AG_SetError(_("Invalid file handle (%d)"),
(int)GetLastError());
goto fail;
}
while (FindNextFile(h, &fdata) != 0) {
dir->ents = Realloc(dir->ents,
(dir->nents+1)*sizeof(char *));
dir->ents[dir->nents++] = Strdup(fdata.cFileName);
}
rv = GetLastError();
FindClose(h);
if (rv != ERROR_NO_MORE_FILES) {
AG_SetError("FindNextFileError (%lu)", rv);
goto fail;
}
}
#else /* !_WIN32 */
{
DIR *dp;
struct dirent *dent;
if ((dp = opendir(path)) == NULL) {
AG_SetError(_("%s: Failed to open directory (%s)"),
path, strerror(errno));
goto fail;
}
while ((dent = readdir(dp)) != NULL) {
dir->ents = Realloc(dir->ents,
(dir->nents+1)*sizeof(char *));
dir->ents[dir->nents++] = Strdup(dent->d_name);
}
closedir(dp);
}
#endif /* _WIN32 */
return (dir);
fail:
Free(dir);
return (NULL);
}
void
AG_CloseDir(AG_Dir *dir)
{
int i;
for (i = 0; i < dir->nents; i++) {
Free(dir->ents[i]);
}
Free(dir->ents);
Free(dir);
}
int
AG_MkPath(const char *path)
{
AG_FileInfo info;
char *pathp, *slash;
int done = 0;
int rv;
slash = pathp = Strdup(path);
while (!done) {
slash += strspn(slash, AG_PATHSEP);
slash += strcspn(slash, AG_PATHSEP);
done = (*slash == '\0');
*slash = '\0';
if (AG_GetFileInfo(pathp, &info) == -1) {
if ((rv = AG_FileExists(pathp)) == -1) {
goto fail;
} else if (rv == 0) {
if (AG_MkDir(pathp) == -1)
goto fail;
}
} else if (info.type != AG_FILE_DIRECTORY) {
AG_SetError(_("%s: Existing file"), pathp);
goto fail;
}
*slash = AG_PATHSEPCHAR;
}
Free(pathp);
return (0);
fail:
Free(pathp);
return (-1);
}
int
AG_GetCWD(char *buf, size_t len)
{
#ifdef _WIN32
DWORD rv;
if ((rv = GetCurrentDirectory(len, buf)) == 0) {
AG_SetError(_("Failed to get current directory (%d)"),
(int)GetLastError());
return (-1);
} else if (rv > len) {
AG_SetError(_("Failed to get current directory (%s)"),
_("Path name is too long"));
return (-1);
}
return (0);
#else
if (getcwd(buf, len) == NULL) {
AG_SetError(_("Failed to get current directory (%s)"),
strerror(errno));
return (-1);
}
return (0);
#endif
}