This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[1.7] Bug in link() with long filenames


It seems that the st_nlink count is not updated for very long file
names. If the filename length is 247, everything is fine. If it is
248...the link count does not get updated, although the files (original
and the link) both have the same st_ino value.

Here's a test case (takes an optional argument that sets the smaller of
the two filename lengths; defaults to 247, which demonstrates the problem).

$ ./longlink
orig1(247):
/tmp/test_longlink/f/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
link1(247):
/tmp/test_longlink/l/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr
orig2(248):
/tmp/test_longlink/f/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
link2(248):
/tmp/test_longlink/l/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs


ino: 11821949022413710
dev: 11821950991284627
nlink: 1
ino: 11540474045703055
dev: 11540476014573971
nlink: 1

after link (namelen 247):
original file
ino: 11821949022413710
dev: 11821950991284627
nlink: 2
link
ino: 11821949022413710
dev: 11821950991284627
nlink: 2

after link (namelen 248):
original file
ino: 11540474045703055
dev: 11540476014573971
nlink: 1
link
ino: 11540474045703055
dev: 11540476014573971
nlink: 1

Any idea why "247" is a magic number?

--
Chuck

#include <stdio.h>
#include <sys/stat.h>

#define ORIGPATH "/tmp/test_longlink/f"
#define LINKPATH "/tmp/test_longlink/l"

void do_stat(const char * s)
{
  struct stat st;
  if (lstat(s, &st) != 0)
  {
    fprintf(stderr, "problem with stat(%s,...)", s);
    return;
  }
  fprintf(stderr, "ino: %llu\n", st.st_ino);
  fprintf(stderr, "dev: %llu\n", st.st_dev);
  fprintf(stderr, "nlink: %d\n", st.st_nlink);
}

int main(int argc, char *argv[])
{
  char orig1[1024];
  char orig2[1024];
  char link1[1024];
  char link2[1024];
  char name[1024];
  int len = 247;
  size_t baselen, newlen;
  FILE* f;

  if (argv[1] && *argv[1])
  {
    len = atoi(argv[1]);
  }

  mkdir("/tmp/test_longlink", 0755);
  mkdir(ORIGPATH, 0755);
  mkdir(LINKPATH, 0755);
  strcpy(orig1, ORIGPATH);
  strcpy(orig2, ORIGPATH);
  strcpy(link1, LINKPATH);
  strcpy(link2, LINKPATH);
  strcat(orig1, "/");
  strcat(orig2, "/");
  strcat(link1, "/");
  strcat(link2, "/");

  baselen = strlen(orig1);
  newlen = baselen;
  while (newlen < len)
  {
    char a = ((char)((newlen - baselen) % 26)) + 'a';
    orig1[newlen] = a;
    link1[newlen] = a;
    newlen++;
  }
  orig1[newlen] = '\0';
  link1[newlen] = '\0';

  newlen = baselen;
  while (newlen < len + 1)
  {
    char a = ((char)((newlen - baselen) % 26)) + 'a';
    orig2[newlen] = a;
    link2[newlen] = a;
    newlen++;
  }
  orig2[newlen] = '\0';
  link2[newlen] = '\0';

  fprintf(stderr, "orig1(%d): %s\n", strlen(orig1), orig1);
  fprintf(stderr, "link1(%d): %s\n", strlen(link1), link1);
  fprintf(stderr, "orig2(%d): %s\n", strlen(orig2), orig2);
  fprintf(stderr, "link2(%d): %s\n", strlen(link2), link2);
  fprintf(stderr, "\n\n");

  f = fopen(orig1, "wb");
  fprintf(f, "%s\n", orig1);
  fclose(f);
  do_stat(orig1);

  f = fopen(orig2, "wb");
  fprintf(f, "%s\n", orig2);
  fclose(f);
  do_stat(orig2);

  link (orig1, link1);
  fprintf(stderr, "\nafter link (namelen %d):\n", strlen(orig1));
  fprintf(stderr, "original file\n");
  do_stat(orig1);
  fprintf(stderr, "link\n");
  do_stat(link1);

  link (orig2, link2);
  fprintf(stderr, "\nafter link (namelen %d):\n", strlen(orig2));
  fprintf(stderr, "original file\n");
  do_stat(orig2);
  fprintf(stderr, "link\n");
  do_stat(link2);

  return 0;
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]