1160814Ssimon/* 2296341Sdelphij * $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp 3296341Sdelphij * $ 4296341Sdelphij */ 5296341Sdelphij/* 6160814Ssimon * Copyright (c) 2004, Richard Levitte <richard@levitte.org> 7160814Ssimon * All rights reserved. 8160814Ssimon * 9160814Ssimon * Redistribution and use in source and binary forms, with or without 10160814Ssimon * modification, are permitted provided that the following conditions 11160814Ssimon * are met: 12160814Ssimon * 1. Redistributions of source code must retain the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer. 14160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 15160814Ssimon * notice, this list of conditions and the following disclaimer in the 16160814Ssimon * documentation and/or other materials provided with the distribution. 17296341Sdelphij * 18160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19160814Ssimon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20160814Ssimon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21160814Ssimon * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22160814Ssimon * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24160814Ssimon * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25160814Ssimon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26160814Ssimon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27160814Ssimon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28160814Ssimon * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29160814Ssimon */ 30160814Ssimon 31160814Ssimon#include <stddef.h> 32160814Ssimon#include <stdlib.h> 33160814Ssimon#include <limits.h> 34160814Ssimon#include <string.h> 35160814Ssimon#include <sys/types.h> 36160814Ssimon#include <dirent.h> 37160814Ssimon#include <errno.h> 38160814Ssimon#ifndef LPDIR_H 39296341Sdelphij# include "LPdir.h" 40160814Ssimon#endif 41160814Ssimon 42296341Sdelphij/* 43296341Sdelphij * The POSIXly macro for the maximum number of characters in a file path is 44296341Sdelphij * NAME_MAX. However, some operating systems use PATH_MAX instead. 45296341Sdelphij * Therefore, it seems natural to first check for PATH_MAX and use that, and 46296341Sdelphij * if it doesn't exist, use NAME_MAX. 47296341Sdelphij */ 48160814Ssimon#if defined(PATH_MAX) 49160814Ssimon# define LP_ENTRY_SIZE PATH_MAX 50160814Ssimon#elif defined(NAME_MAX) 51160814Ssimon# define LP_ENTRY_SIZE NAME_MAX 52160814Ssimon#endif 53160814Ssimon 54296341Sdelphij/* 55296341Sdelphij * Of course, there's the possibility that neither PATH_MAX nor NAME_MAX 56296341Sdelphij * exist. It's also possible that NAME_MAX exists but is define to a very 57296341Sdelphij * small value (HP-UX offers 14), so we need to check if we got a result, and 58296341Sdelphij * if it meets a minimum standard, and create or change it if not. 59296341Sdelphij */ 60160814Ssimon#if !defined(LP_ENTRY_SIZE) || LP_ENTRY_SIZE<255 61160814Ssimon# undef LP_ENTRY_SIZE 62160814Ssimon# define LP_ENTRY_SIZE 255 63160814Ssimon#endif 64160814Ssimon 65296341Sdelphijstruct LP_dir_context_st { 66296341Sdelphij DIR *dir; 67296341Sdelphij char entry_name[LP_ENTRY_SIZE + 1]; 68160814Ssimon}; 69160814Ssimon 70160814Ssimonconst char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) 71160814Ssimon{ 72296341Sdelphij struct dirent *direntry = NULL; 73160814Ssimon 74296341Sdelphij if (ctx == NULL || directory == NULL) { 75296341Sdelphij errno = EINVAL; 76296341Sdelphij return 0; 77160814Ssimon } 78160814Ssimon 79296341Sdelphij errno = 0; 80296341Sdelphij if (*ctx == NULL) { 81296341Sdelphij *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); 82296341Sdelphij if (*ctx == NULL) { 83296341Sdelphij errno = ENOMEM; 84296341Sdelphij return 0; 85296341Sdelphij } 86296341Sdelphij memset(*ctx, '\0', sizeof(LP_DIR_CTX)); 87160814Ssimon 88296341Sdelphij (*ctx)->dir = opendir(directory); 89296341Sdelphij if ((*ctx)->dir == NULL) { 90296341Sdelphij int save_errno = errno; /* Probably not needed, but I'm paranoid */ 91296341Sdelphij free(*ctx); 92296341Sdelphij *ctx = NULL; 93296341Sdelphij errno = save_errno; 94296341Sdelphij return 0; 95296341Sdelphij } 96160814Ssimon } 97160814Ssimon 98296341Sdelphij direntry = readdir((*ctx)->dir); 99296341Sdelphij if (direntry == NULL) { 100296341Sdelphij return 0; 101160814Ssimon } 102160814Ssimon 103296341Sdelphij strncpy((*ctx)->entry_name, direntry->d_name, 104296341Sdelphij sizeof((*ctx)->entry_name) - 1); 105296341Sdelphij (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0'; 106296341Sdelphij return (*ctx)->entry_name; 107160814Ssimon} 108160814Ssimon 109160814Ssimonint LP_find_file_end(LP_DIR_CTX **ctx) 110160814Ssimon{ 111296341Sdelphij if (ctx != NULL && *ctx != NULL) { 112296341Sdelphij int ret = closedir((*ctx)->dir); 113160814Ssimon 114296341Sdelphij free(*ctx); 115296341Sdelphij switch (ret) { 116296341Sdelphij case 0: 117296341Sdelphij return 1; 118296341Sdelphij case -1: 119296341Sdelphij return 0; 120296341Sdelphij default: 121296341Sdelphij break; 122296341Sdelphij } 123160814Ssimon } 124296341Sdelphij errno = EINVAL; 125296341Sdelphij return 0; 126160814Ssimon} 127