/*
 * SPDX-FileCopyrightText: 2026 Didier Kryn <kryn@in2p3.fr>
 * 
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
/*           char *devpath(const char *devname, char *namebuf)           */
/*-----------------------------------------------------------------------*/
/* Browse /sys/devices to find a subdirectory with the name devname.     */
/* Return the absolute path to this directory. Return NULL if not found  */
/* namebuf is a working buffer large enough to contain the path. Better  */
/* provide PATH_MAX chars, as defined in <limits.h>                      */
/*-----------------------------------------------------------------------*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include "slash_sys.h"

/*--------------- hidden function which does all the work: --------------*/
static char *digsys(const char *, const char *, char *namebuf);

/*------------------------------ The API --------------------------------*/
char *devpath(const char *devname, char *namebuf)
{
  return digsys("/sys/devices", devname, namebuf);
}

/* dig recursively into pathname to find a subdir named findname */
/* we use lstat because we don't want to dereference symlinks    */
static char *digsys( const char *pathname, const char *findname,
		     char namebuf[NAME_MAX+1] )
{
  struct stat mystat;
  char *foundname;
  DIR *dirp;
  struct dirent *bdir;
  struct stat   bstat;
  int pathsize;

  foundname = NULL;
  if( lstat(pathname, &mystat) ) return NULL;
  /* Only consider directories */
  if ( ! S_ISDIR(mystat.st_mode) ) return NULL;
  dirp = opendir ( pathname );
  if( !dirp ) return NULL;
  while ( (bdir=readdir(dirp)) )
    {
      if (!strcmp(bdir->d_name, ".") || !strcmp(bdir->d_name, "..") )
	continue;
      pathsize = strlen(pathname) + strlen(bdir->d_name) + 2;
      {
	char newpath[pathsize];
	strcpy(newpath, pathname);
	strcat(newpath, "/");
	strcat(newpath, bdir->d_name);
	lstat (newpath, &bstat);
	/* only consider directories */
	if (S_ISDIR(bstat.st_mode) )
	  {
	    if( !strcmp(bdir->d_name, findname) )
	      {
		/* BINGO ! */
		strcpy(namebuf, pathname);
		strcat(namebuf, "/");
		strcat(namebuf, findname);
		foundname = namebuf;
		break;
	      }
	    else
	      {
		/* otherwise invoke ourself recursively */
		foundname = digsys ( newpath, findname, namebuf );
		if(foundname) break;
	      }
	  }
      }
    }
  closedir(dirp);
  return foundname;
}
