#include "smbw.h"
#include "bsd-strlfunc.h"
int smbw_dirp(DIR * dirp)
{
return ((char *) dirp >= (char *) smbw_fd_map &&
(char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
*(int *) dirp != -1);
}
int smbw_getdents(unsigned int fd_smbw,
struct SMBW_dirent *dirent_external,
int count)
{
int remaining;
int fd_client = smbw_fd_map[fd_smbw];
struct smbc_dirent *dirent_internal;
for (remaining = count;
remaining > sizeof(struct SMBW_dirent);
dirent_external++) {
dirent_internal = smbc_readdir(fd_client);
if (dirent_internal == NULL) {
break;
}
remaining -= sizeof(struct SMBW_dirent);
dirent_external->d_ino = -1;
dirent_external->d_off = smbc_telldir(fd_client);
dirent_external->d_reclen = sizeof(struct SMBW_dirent);
dirent_external->d_type = dirent_internal->smbc_type;
smbw_strlcpy(dirent_external->d_name,
dirent_internal->name,
sizeof(dirent_external->d_name) - 1);
smbw_strlcpy(dirent_external->d_comment,
dirent_internal->comment,
sizeof(dirent_external->d_comment) - 1);
}
return(count - remaining);
}
int smbw_chdir(const char *name)
{
int simulate;
struct stat statbuf;
char path[PATH_MAX];
char *p;
SMBW_INIT();
if (!name) {
errno = EINVAL;
return -1;
}
if (! smbw_path((char *) name)) {
if ((* smbw_libc.chdir)(name) == 0) {
*smbw_cwd = '\0';
return 0;
}
return -1;
}
smbw_fix_path(name, path);
p = path + 6;
simulate = (strchr(p, '/') == NULL);
if (! simulate) {
if (smbc_stat(path, &statbuf) < 0) {
return -1;
}
if (! S_ISDIR(statbuf.st_mode)) {
errno = ENOTDIR;
return -1;
}
}
smbw_strlcpy(smbw_cwd, path, PATH_MAX);
(* smbw_libc.chdir)("/");
return 0;
}
int smbw_mkdir(const char *fname, mode_t mode)
{
char path[PATH_MAX];
if (!fname) {
errno = EINVAL;
return -1;
}
SMBW_INIT();
smbw_fix_path(fname, path);
return smbc_mkdir(path, mode);
}
int smbw_rmdir(const char *fname)
{
char path[PATH_MAX];
if (!fname) {
errno = EINVAL;
return -1;
}
SMBW_INIT();
smbw_fix_path(fname, path);
return smbc_rmdir(path);
}
char *smbw_getcwd(char *buf, size_t size)
{
SMBW_INIT();
if (*smbw_cwd == '\0') {
return (* smbw_libc.getcwd)(buf, size);
}
if (buf == NULL) {
if (size == 0) {
size = strlen(smbw_cwd) + 1;
}
buf = malloc(size);
if (buf == NULL) {
errno = ENOMEM;
return NULL;
}
}
smbw_strlcpy(buf, smbw_cwd, size);
buf[size-1] = '\0';
return buf;
}
int smbw_fchdir(int fd_smbw)
{
int ret;
SMBW_INIT();
if (! smbw_fd(fd_smbw)) {
ret = (* smbw_libc.fchdir)(fd_smbw);
(void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX);
return ret;
}
errno = EACCES;
return -1;
}
DIR *smbw_opendir(const char *fname)
{
int fd_client;
int fd_smbw;
char path[PATH_MAX];
DIR * dirp;
SMBW_INIT();
if (!fname) {
errno = EINVAL;
return NULL;
}
fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
if (fd_smbw == -1) {
errno = EMFILE;
return NULL;
}
smbw_fix_path(fname, path);
fd_client = smbc_opendir(path);
if (fd_client < 0) {
(* smbw_libc.close)(fd_smbw);
return NULL;
}
smbw_fd_map[fd_smbw] = fd_client;
smbw_ref(fd_client, SMBW_RCT_Increment);
dirp = (DIR *) &smbw_fd_map[fd_smbw];
return dirp;
}
struct SMBW_dirent *smbw_readdir(DIR *dirp)
{
int fd_smbw;
int fd_client;
struct smbc_dirent *dirent_internal;
static struct SMBW_dirent dirent_external;
fd_smbw = (int *) dirp - smbw_fd_map;
fd_client = smbw_fd_map[fd_smbw];
if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
return NULL;
}
dirent_external.d_ino = -1;
dirent_external.d_off = smbc_telldir(fd_client);
dirent_external.d_reclen = sizeof(struct SMBW_dirent);
dirent_external.d_type = dirent_internal->smbc_type;
smbw_strlcpy(dirent_external.d_name,
dirent_internal->name,
sizeof(dirent_external.d_name) - 1);
smbw_strlcpy(dirent_external.d_comment,
dirent_internal->comment,
sizeof(dirent_external.d_comment) - 1);
return &dirent_external;
}
int smbw_readdir_r(DIR *dirp,
struct SMBW_dirent *__restrict entry,
struct SMBW_dirent **__restrict result)
{
SMBW_dirent *dirent;
dirent = smbw_readdir(dirp);
if (dirent != NULL) {
*entry = *dirent;
if (result != NULL) {
*result = entry;
}
return 0;
}
if (result != NULL) {
*result = NULL;
}
return EBADF;
}
int smbw_closedir(DIR *dirp)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
(* smbw_libc.close)(fd_smbw);
if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
return 0;
}
smbw_fd_map[fd_smbw] = -1;
return smbc_closedir(fd_client);
}
void smbw_seekdir(DIR *dirp, long long offset)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
smbc_lseekdir(fd_client, offset);
}
long long smbw_telldir(DIR *dirp)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
return (long long) smbc_telldir(fd_client);
}