Show file.c syntax highlighted
/*
*
* Copyright (c) 2003 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:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - 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.
*
*/
/*
* file-related utilities
*
* part of libmisc
*
* $Id: file.c,v 1.10 2005/07/05 01:33:52 girod Exp $
*/
char misc_file_c_cvsid[] = "$Id: file.c,v 1.10 2005/07/05 01:33:52 girod Exp $";
#include "misc.h"
#include <libdev/glib_dev.h>
#include <sys/poll.h>
/* returns true if this device is poll-capable */
int pollable(int fd)
{
struct pollfd pfd = {
fd: fd,
events: POLLIN | POLLPRI | POLLERR
};
int count;
int i;
/* poll fails second time ? */
for (i=0; i<2; i++) {
count = poll(&pfd, 1, 0);
/* check for return -1 */
if (count < 0)
return 0;
/* check for return 1, with error */
if ((count == 1) && (pfd.revents & POLLERR))
return 0;
ioctl(fd, 0, 0);
}
/* all OK */
return 1;
}
/* polls the device and returns current event set */
int pollnow(int fd)
{
struct pollfd pfd = {
fd: fd,
events: POLLIN | POLLOUT | POLLHUP | POLLPRI | POLLERR
};
int count = poll(&pfd, 1, 0);
/* check for return -1 */
if (count < 0)
return -1;
/* check for return 1, with error */
if ((count == 1) && (pfd.revents & POLLERR))
return -1;
/* return poll state using FUSD flags */
int retval = 0;
if (count == 1) {
if (pfd.revents & POLLIN)
retval |= FUSD_NOTIFY_INPUT;
if (pfd.revents & POLLOUT)
retval |= FUSD_NOTIFY_OUTPUT;
if (pfd.revents & (POLLHUP | POLLPRI))
retval |= FUSD_NOTIFY_EXCEPT;
}
return retval;
}
//
// Write a buffer to an fd until the entire buffer is consumed.
// Returns 0 on success, -1 on failure.
//
int write_to_fd(int fd, const void *buf, int len)
{
int status;
while (len > 0) {
status = write(fd, buf, len);
if (status >= 0) {
buf += status;
len -= status;
} else {
return status;
}
}
return 0;
}
//
// Open a file, write a null-terminated string to the file, close it
//
int write_to_file(const char *file, const char *s)
{
int fd, retval;
if ((fd = open(file, O_RDWR | O_CREAT | O_NONBLOCK, 0666)) < 0)
return fd;
retval = write_to_fd(fd, s, strlen(s));
close(fd);
return retval;
}
int printf_to_file(const char *file, const char *fmt, ...)
{
va_list ap;
static char str[MAX_LINE];
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
return write_to_file(file, str);
}
//
// Open a file, do a read, close it
//
int read_from_file(const char *file, char *s, size_t size)
{
int fd, retval;
if ((fd = open(file, O_RDONLY)) < 0)
return fd;
if ((retval = read(fd, s, size-1)) >= 0)
s[retval] = '\0';
close(fd);
return retval;
}
//
// Read a structure from a file. Checks to make sure that the size of
// the file is exactly the size of the structure. Returns -1 on err,
// 0 if it succeeds in reading exactly as many bytes as the struct size.
//
int read_struct_from_file(const char *file, void *p, size_t size)
{
int fd = -1, retval;
struct stat statbuf;
if ((fd = open(file, O_RDONLY)) < 0) {
elog(LOG_WARNING, "opening %s: %m", file);
return fd;
}
if (fstat(fd, &statbuf) < 0) {
elog(LOG_WARNING, "couldn't stat %s: %m", file);
retval = -errno;
goto done;
}
/* make sure the file has exactly as many bytes as we expect:
* neither more nor less */
if (statbuf.st_size != size) {
elog(LOG_WARNING, "%s size mismatch: wanted %d bytes, file has %d", file, size, (int) statbuf.st_size);
retval = -EINVAL;
goto done;
}
if ((retval = read(fd, p, size)) < 0) {
elog(LOG_WARNING, "reading from %s: %m", file);
retval = -errno;
goto done;
}
if (retval != size) {
elog(LOG_WARNING, "%s size mismatch(2): wanted %d bytes, file has %d", file, size, (int) statbuf.st_size);
retval = -EINVAL;
goto done;
}
/* success! */
retval = 0;
done:
if (fd > 0)
close(fd);
if (retval < 0) {
errno = -retval;
return -1;
} else {
errno = 0;
return 0;
}
}
//
// Read a structure from a file. Checks to make sure that the size of
// the file is exactly the size of the structure. Returns -1 on err,
// 0 if it succeeds in reading exactly as many bytes as the struct size.
//
int write_struct_to_file(const char *file, void *p, size_t size)
{
int fd, retval = -1;
if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
return fd;
if ((retval = write_to_fd(fd, p, size)) < 0)
goto done;
fsync(fd);
/* success! */
retval = 0;
done:
close(fd);
return retval;
}
/*
* make an FD blocking or nonblocking; returns 0 on success, -1 on
* error
*/
int set_nonblock(int fd, int enable_nonblock)
{
int retval, flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
return flags;
if (enable_nonblock)
flags |= O_NONBLOCK;
else
flags &= ~O_NONBLOCK;
if ((retval = fcntl(fd, F_SETFL, flags)) < 0)
return retval;
return 0;
}
/*
* do ioctl
*/
int do_ioctl(int fd, int cmd, int arg, const char *note)
{
int status = ioctl(fd, cmd, &arg);
if (status < 0) {
elog(LOG_WARNING, ": ioctl %x (%s) failed on fd %d: %m",
cmd, note, fd);
}
return status;
}
/*
* mkdir_with_parents: given a pathname, create a directory with that
* name and possibly any parents of that directory, if necessary.
*
* Returns:
* 0 if the directory was created successfully (or already existed)
* -1 with errno set appropriately if there was an error creating the
* directory or any of its parents
*/
int mkdir_with_parents(const char *path_orig)
{
char path[PATH_MAX+1];
char *parent_end;
if (path_orig == NULL || strlen(path_orig) > PATH_MAX) {
elog(LOG_ERR, "bad argument");
return -1;
}
strcpy(path, path_orig);
/* skip over any leading slashes, then find the first slash after
* that */
parent_end = index(path + strspn(path, "/"), '/');
/* now, for each component of the path, create the dir */
while (parent_end != NULL) {
*parent_end = '\0';
if (mkdir(path, 0777) < 0 && errno != EEXIST) {
elog(LOG_ERR, "trying to create directory %s: %m", path);
return -1;
}
*parent_end = '/';
parent_end = index(parent_end+1, '/');
}
if (mkdir(path, 0777) < 0 && errno != EEXIST) {
elog(LOG_ERR, "trying to create directory %s: %m", path);
return -1;
} else {
return 0;
}
}
See more files for this project here