bug#1205: [BusyBox] bug#1205: mount handles links differently in 0.60
Vladimir N. Oleynik
dzo at simtreas.ru
Thu Aug 9 11:45:02 UTC 2001
Matt Kraai wrote:
>
> On Thu, Aug 09, 2001 at 05:46:15PM +0400, Vladimir N. Oleynik wrote:
> > Manuel.
> > As a result of this not so beautiful dispute the beautiful idea was born: look
> > at realization strcpy_overlap() from this text. It is full analogue Uclibc
> > strcpy() but on
> > 14 bytes less (noninline - 10 bytes less :-0 ).
> >
> > Matt.
> > Result more on these bytes (the total difference with your variant makes 66
> > bytes and my variant seems to me much faster thanking inline "special" strcpy).
>
> By simplifying the code to remove extra slashes, and using your
> new function, the following simplify_path is 17 bytes smaller than
> yours (when compiled on busybox.net with -Os).
Thank for new stimulus. 6 bytes I have made a difference, but it was necessary
to renounce
as well as to you in the speed - to remove dual slashsc for once instead of all
in
succession going.
;-))
--w
vodz
-------------- next part --------------
#include "libbb/libbb.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
/* Matt suggestion: strcpy rescue use with overlap */
static inline char *strcpy_overlap(char *dst, const char *src)
{
char *ptr = dst;
do *dst++ = *src; while (*src++);
return ptr;
}
#ifdef MATT
#if 0
/* Chop out LEN bytes of a string, starting at S. */
static void strchop(char *s, size_t len)
{
memmove(s, s + len, strlen(s + len) + 1);
}
#endif
#define strchop(S, LEN) strcpy_overlap((S), (S) + (LEN))
/* Change PATH to an absolute path, remove duplicate and trailing
* slashes, and eliminate `.' and `..' components. */
char *simplify_path(const char *path)
{
char *s;
int i, j;
/* Make the pathname absolute. */
if (path[0] == '/')
s = xstrdup(path);
else {
char *cwd = xgetcwd(NULL);
s = concat_path_file(cwd, path);
free(cwd);
}
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == '/') {
/* Strip extra slashes. */
if (s[i+1] == '/') {
strchop(s+i+1, 1);
i--;
/* Strip the trailing slash. */
} else if (i != 0 && s[i+1] == '\0')
s[i] = '\0';
else if (s[i+1] == '.') {
/* Remove `.' components. */
if (s[i+2] == '\0' || s[i+2] == '/') {
strchop(s+i+1, 1);
i--;
/* Remove `..' components. */
} else if (s[i+2] == '.' && (s[i+3] == '\0' || s[i+3] == '/')) {
for (j = i - 1; 0 < j && s[j] != '/'; j--)
/* Loop. */;
if (j < 0)
j = 0;
strchop(s+j+1, (i - j) + 2);
i = j - 1;
}
}
}
}
return s;
}
#else
char *simplify_path(const char *path)
{
char *s, *start, *next;
if (path[0] == '/')
start = xstrdup(path);
else {
s = xgetcwd(NULL);
start = concat_path_file(s, path);
free(s);
}
s = start;
/* remove . and .. */
while(*s) {
if(*s++ == '/' && (*s == '/' || (*s == 0 && s!=(start+1)))) {
/* remove duplicate and trailing slashes */
s = strcpy_overlap(s-1, s);
}
else if(*(s-1) == '.' && *(s-2)=='/') {
if(*s == '/' || *s == 0) {
/* remove . */
s = strcpy_overlap(s-1, s); /* maybe set // */
s--;
}
else if(*s == '.' && (*(s+1) == '/' || *(s+1) == 0)) {
/* remove "dir/.." */
next = s+1; /* set after ".." */
/* skip previous slashes */
for(s -= 2; s>start && *s == '/'; s--)
;
/* skip previous dir */
while(*s != '/') s--;
/* remove previous dir */
strcpy_overlap(s, next); /* maybe set // */
}
}
}
return start;
}
#endif
const char *applet_name = "sla";
int main(void)
{
char buf[80];
char *s;
int l;
for(;;) {
printf("test => ");
if(fgets(buf, 80, stdin)==NULL)
return 0;
l = strlen(buf);
if(l<=1)
return 0;
buf[l-1]=0;
s = simplify_path(buf);
printf("path => %s\n", s);
free(s);
}
}
More information about the busybox
mailing list