1160814Ssimon/* $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp $ */
2160814Ssimon/*
3160814Ssimon * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
4160814Ssimon * All rights reserved.
5160814Ssimon *
6160814Ssimon * Redistribution and use in source and binary forms, with or without
7160814Ssimon * modification, are permitted provided that the following conditions
8160814Ssimon * are met:
9160814Ssimon * 1. Redistributions of source code must retain the above copyright
10160814Ssimon *    notice, this list of conditions and the following disclaimer.
11160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
12160814Ssimon *    notice, this list of conditions and the following disclaimer in the
13160814Ssimon *    documentation and/or other materials provided with the distribution.
14160814Ssimon *
15160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16160814Ssimon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17160814Ssimon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18160814Ssimon * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19160814Ssimon * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21160814Ssimon * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22160814Ssimon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23160814Ssimon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24160814Ssimon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25160814Ssimon * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26160814Ssimon */
27160814Ssimon
28160814Ssimon#include <stddef.h>
29160814Ssimon#include <stdlib.h>
30160814Ssimon#include <limits.h>
31160814Ssimon#include <string.h>
32160814Ssimon#include <sys/types.h>
33160814Ssimon#include <dirent.h>
34160814Ssimon#include <errno.h>
35160814Ssimon#ifndef LPDIR_H
36160814Ssimon#include "LPdir.h"
37160814Ssimon#endif
38160814Ssimon
39160814Ssimon/* The POSIXly macro for the maximum number of characters in a file path
40160814Ssimon   is NAME_MAX.  However, some operating systems use PATH_MAX instead.
41160814Ssimon   Therefore, it seems natural to first check for PATH_MAX and use that,
42160814Ssimon   and if it doesn't exist, use NAME_MAX. */
43160814Ssimon#if defined(PATH_MAX)
44160814Ssimon# define LP_ENTRY_SIZE PATH_MAX
45160814Ssimon#elif defined(NAME_MAX)
46160814Ssimon# define LP_ENTRY_SIZE NAME_MAX
47160814Ssimon#endif
48160814Ssimon
49160814Ssimon/* Of course, there's the possibility that neither PATH_MAX nor NAME_MAX
50160814Ssimon   exist.  It's also possible that NAME_MAX exists but is define to a
51160814Ssimon   very small value (HP-UX offers 14), so we need to check if we got a
52160814Ssimon   result, and if it meets a minimum standard, and create or change it
53160814Ssimon   if not. */
54160814Ssimon#if !defined(LP_ENTRY_SIZE) || LP_ENTRY_SIZE<255
55160814Ssimon# undef LP_ENTRY_SIZE
56160814Ssimon# define LP_ENTRY_SIZE 255
57160814Ssimon#endif
58160814Ssimon
59160814Ssimonstruct LP_dir_context_st
60160814Ssimon{
61160814Ssimon  DIR *dir;
62160814Ssimon  char entry_name[LP_ENTRY_SIZE+1];
63160814Ssimon};
64160814Ssimon
65160814Ssimonconst char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
66160814Ssimon{
67160814Ssimon  struct dirent *direntry = NULL;
68160814Ssimon
69160814Ssimon  if (ctx == NULL || directory == NULL)
70160814Ssimon    {
71160814Ssimon      errno = EINVAL;
72160814Ssimon      return 0;
73160814Ssimon    }
74160814Ssimon
75160814Ssimon  errno = 0;
76160814Ssimon  if (*ctx == NULL)
77160814Ssimon    {
78160814Ssimon      *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX));
79160814Ssimon      if (*ctx == NULL)
80160814Ssimon	{
81160814Ssimon	  errno = ENOMEM;
82160814Ssimon	  return 0;
83160814Ssimon	}
84160814Ssimon      memset(*ctx, '\0', sizeof(LP_DIR_CTX));
85160814Ssimon
86160814Ssimon      (*ctx)->dir = opendir(directory);
87160814Ssimon      if ((*ctx)->dir == NULL)
88160814Ssimon	{
89160814Ssimon	  int save_errno = errno; /* Probably not needed, but I'm paranoid */
90160814Ssimon	  free(*ctx);
91160814Ssimon	  *ctx = NULL;
92160814Ssimon	  errno = save_errno;
93160814Ssimon	  return 0;
94160814Ssimon	}
95160814Ssimon    }
96160814Ssimon
97160814Ssimon  direntry = readdir((*ctx)->dir);
98160814Ssimon  if (direntry == NULL)
99160814Ssimon    {
100160814Ssimon      return 0;
101160814Ssimon    }
102160814Ssimon
103160814Ssimon  strncpy((*ctx)->entry_name, direntry->d_name, sizeof((*ctx)->entry_name) - 1);
104160814Ssimon  (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
105160814Ssimon  return (*ctx)->entry_name;
106160814Ssimon}
107160814Ssimon
108160814Ssimonint LP_find_file_end(LP_DIR_CTX **ctx)
109160814Ssimon{
110160814Ssimon  if (ctx != NULL && *ctx != NULL)
111160814Ssimon    {
112160814Ssimon      int ret = closedir((*ctx)->dir);
113160814Ssimon
114160814Ssimon      free(*ctx);
115160814Ssimon      switch (ret)
116160814Ssimon	{
117160814Ssimon	case 0:
118160814Ssimon	  return 1;
119160814Ssimon	case -1:
120160814Ssimon	  return 0;
121160814Ssimon	default:
122160814Ssimon	  break;
123160814Ssimon	}
124160814Ssimon    }
125160814Ssimon  errno = EINVAL;
126160814Ssimon  return 0;
127160814Ssimon}
128