cdrtools/libschily/lxchdir.c

83 lines
1.7 KiB
C
Raw Normal View History

2025-06-15 04:19:58 +08:00
/* @(#)lxchdir.c 1.1 11/10/21 Copyright 2004-2011 J. Schilling */
/*
* Long path name aware chdir().
*
* The code has been adopted from libfind.
*
* Copyright (c) 2004-2011 J. Schilling
*/
/*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* See the file CDDL.Schily.txt in this distribution for details.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file CDDL.Schily.txt from this distribution.
*/
#include <schily/unistd.h>
#include <schily/types.h>
#include <schily/fcntl.h>
#include <schily/maxpath.h>
#include <schily/string.h>
#include <schily/errno.h>
#include <schily/standard.h>
#include <schily/schily.h>
#include "at-defs.h"
#ifndef ENAMETOOLONG
#define ENAMETOOLONG EINVAL
#endif
EXPORT int lxchdir __PR((char *p));
LOCAL int xchdir __PR((char *p));
EXPORT int
lxchdir(p)
char *p;
{
if (chdir(p) < 0) {
if (geterrno() != ENAMETOOLONG)
return (-1);
return (xchdir(p));
}
return (0);
}
LOCAL int
xchdir(p)
char *p;
{
char *p2;
BOOL first = TRUE;
while (*p) {
if ((p2 = strchr(p, '/')) != NULL)
*p2 = '\0';
if (first && p2 && p[0] == '\0') {
if (chdir("/") < 0)
return (-1);
} else {
/*
* If this is not the first chdir() and we are doing a
* multi hop chdir(), we may be on an undefined
* intermediate directory. Mark this case by returning
* -2 instead of -1.
*/
if (chdir(p) < 0)
return (first?-1:-2);
}
if (p2 == NULL)
break;
*p2 = '/';
p = &p2[1];
first = FALSE;
}
return (0);
}