#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdarg.h>
#include <unistd.h>
#include <libgen.h>
#include "libdevinfo.h"
static int di_dli_open(char *, int, short, int);
#define DLI_NAME 0x1
char *
di_dli_name(char *path)
{
#define dliroot "/etc/devices/dli/info."
#define dliroot_len (sizeof (dliroot) - 1)
char *dlipath;
int dlipathsz;
char *basep;
basep = basename(path);
dlipathsz = strlen(basep) + dliroot_len + 1;
dlipath = malloc(sizeof (char) * dlipathsz);
(void) snprintf(dlipath, dlipathsz, "%s%s", dliroot, basep);
dlipath[dlipathsz - 1] = '\0';
return (dlipath);
#undef dlipre
#undef dlipre_len
#undef dliroot
#undef dliroot_len
}
static int
di_dli_open(char *path, int oflag, short l_type, int flags)
{
int fd;
char *dlipath, *dlipath_dir, *dlipath_dup;
struct stat statbuf;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
flock_t lock;
dlipath = (flags & DLI_NAME) ? di_dli_name(path) : (char *)path;
dlipath_dup = strdup(dlipath);
dlipath_dir = dirname(dlipath_dup);
if (stat(dlipath_dir, &statbuf) < 0) {
if (mkdirp(dlipath_dir,
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
fd = -1;
goto OUT;
}
}
fd = open(dlipath, oflag, mode);
if (fd < 0)
goto OUT;
if (fchmod(fd, mode) < 0) {
(void) close(fd);
fd = -1;
goto OUT;
}
bzero(&lock, sizeof (lock));
lock.l_type = l_type;
if (fcntl(fd, F_SETLKW, &lock) < 0) {
(void) close(fd);
fd = -1;
}
OUT:
free(dlipath_dup);
if (flags & DLI_NAME)
free(dlipath);
return (fd);
}
int
di_dli_openr(char *path)
{
return (di_dli_open(path, O_RDONLY, F_RDLCK, DLI_NAME));
}
int
di_dli_openw(char *path)
{
return (di_dli_open(path, O_RDWR | O_SYNC | O_TRUNC | O_CREAT,
F_WRLCK, DLI_NAME));
}
void
di_dli_close(int fd)
{
flock_t lock;
if (fd < 0)
return;
bzero(&lock, sizeof (lock));
lock.l_type = F_UNLCK;
(void) fcntl(fd, F_SETLK, &lock);
(void) close(fd);
}