Skip to content

Commit 14b6624

Browse files
Symbolic links are not counted twice.
1 parent c7a259a commit 14b6624

File tree

4 files changed

+82
-38
lines changed

4 files changed

+82
-38
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ Theoretically, version 1.8.2 and older work on windows.
66

77
To install, simply copy the executable file to /usr/bin or /usr/local/bin on BSD, Linux, or OS X.
88

9-
On Microsoft Windows, there is no folder for storing executables, unless you count System32.
9+
On Windows, there is no predefined folder for storing executables, unless you count System32 and related.
1010

11-
To install on Microsoft Windows, copy the executable file to a folder in the PATH enviornment variable.
11+
To install on Windows, copy the executable file to a folder in the PATH enviornment variable.
1212

1313
You may need to modify the PATH variable in the settings and create a new directory if there is no suitable directory.
1414

1515
You may put the executable in a system directory such as System32, and that may work, but is inadvisable.
16+
17+
Having symbolic links may cause an infinite loop.
18+
19+
If original directory to count is ~/u, and ~/u/v is a symbolic link to ~/v, and ~/v/x/y is a symbolic link to ~/v, there will be a loop.
20+
21+
However, if all symbolic links to the files in the same directory, then there will be no infinite loop, and no file is counted twice.
1622
```
1723
clang -O3 -c csloc.c get_sub_dir.c main.c
1824
clang -o csloc csloc.o get_sub_dir.o main.o

csloc.c

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ static inline int has_file_extension(const char *fname, const char *ext)
3434
return status;
3535
}
3636
}
37+
int csloc____ispref(const char *pref, const char *str)
38+
{
39+
int p = 1;
40+
for(; *pref != '\0'; ++pref, ++str)
41+
{
42+
if(*str == '\0')
43+
{
44+
p = 0;
45+
pref = str - 1;
46+
}
47+
else if(*pref != *str)
48+
p = 0;
49+
50+
}
51+
return p;
52+
}
3753
#ifdef _WIN32
3854
long long
3955
#else
@@ -185,6 +201,7 @@ csloc(const char *dir, csloc_filenp *dat, size_t *sz, unsigned ops, size_t cr, c
185201
{
186202
// prepare to get the files and subdirectories
187203
char subdir[3000], lnpath[3000];
204+
char *apath=NULL;
188205
size_t len=strlen(dir), cnt=0;//csloc____cnt_sub_dirs(dir);
189206
strcpy(subdir, dir);
190207
#ifdef _WIN32
@@ -238,12 +255,6 @@ csloc(const char *dir, csloc_filenp *dat, size_t *sz, unsigned ops, size_t cr, c
238255
len=strlen(currf), cnt=csloc____cnt_sub_dirs(currf);
239256
if(cnt <= 2)
240257
continue;
241-
strcpy(subdir, currf);
242-
#ifdef _WIN32
243-
subdir[len]='\\';
244-
#else
245-
subdir[len]='/';
246-
#endif
247258

248259
// get subdirectories and files
249260
names=malloc(sizeof(char*)*cnt);
@@ -255,12 +266,21 @@ csloc(const char *dir, csloc_filenp *dat, size_t *sz, unsigned ops, size_t cr, c
255266
// put all subdirectories in
256267
for(size_t i = 0; i < cnt; ++i)
257268
{
269+
strcpy(subdir, currf);
270+
#ifdef _WIN32
271+
subdir[len]='\\';
272+
#else
273+
subdir[len]='/';
274+
#endif
258275
strcpy(subdir + len + 1, names[i]);
259276

260277
// get rid of hidden files if enabled
261278
redirect:
262279
if(CSLOC_ISIGNDOT(ops) && names[i][0] == '.')
280+
{
281+
free(names[i]);
263282
continue;
283+
}
264284

265285
if(NFILE==tps[i])
266286
{
@@ -312,54 +332,71 @@ csloc(const char *dir, csloc_filenp *dat, size_t *sz, unsigned ops, size_t cr, c
312332
}
313333
sloc += sfl;
314334
}
315-
continue;
316335
}
317336
else if(DIRECTORY==tps[i])
318337
{
319338
// get rid of parent and self
320-
if(strcmp(".", names[i]) == 0 || strcmp("..", names[i]) == 0)
321-
continue;
322-
323-
if(fcnt==rm)
339+
if(strcmp(".", names[i]) != 0 && strcmp("..", names[i]) != 0)
324340
{
325-
stack=realloc(stack, (rm+olr)*sizeof(char*));
326-
csloc_check_pointer(stack);
327-
fcnt=olr;
328-
olr=rm;
329-
rm+=fcnt;
330-
fcnt=olr;
331-
}
341+
realpath(subdir, lnpath);
342+
if(apath==NULL)
343+
apath=realpath(dir,apath);
332344

333-
stack[fcnt]=malloc(strlen(subdir) + 2);
334-
csloc_check_pointer(stack[fcnt]);
335-
strcpy(stack[fcnt], subdir);
336-
fcnt++;
337-
free(names[i]);
345+
if(strcmp(apath, lnpath) != 0)
346+
{
347+
if(fcnt==rm)
348+
{
349+
stack=realloc(stack, (rm+olr)*sizeof(char*));
350+
csloc_check_pointer(stack);
351+
fcnt=olr;
352+
olr=rm;
353+
rm+=fcnt;
354+
fcnt=olr;
355+
}
356+
357+
stack[fcnt]=malloc(strlen(subdir) + 2);
358+
csloc_check_pointer(stack[fcnt]);
359+
strcpy(stack[fcnt], subdir);
360+
fcnt++;
361+
}
362+
}
338363
}
339364
else if(CSLOCSYMLINK==tps[i])
340365
{
341366
realpath(subdir, lnpath);
342-
strcpy(subdir, lnpath);
343-
if(stat(subdir, &fdat) == 0)
367+
if(apath==NULL)
368+
apath=realpath(dir,apath);
369+
if(!csloc____ispref(apath, lnpath))
344370
{
345-
if(S_ISDIR(fdat.st_mode))
346-
tps[i]=DIRECTORY;
347-
else if(S_ISREG(fdat.st_mode))
348-
tps[i]=NFILE;
349-
else
350-
tps[i]=CSLOCOTHER;
351-
goto redirect;
371+
strcpy(subdir, lnpath);
372+
realpath(currf, lnpath);
373+
if(!csloc____ispref(lnpath, subdir))
374+
{
375+
if(stat(subdir, &fdat)==0)
376+
{
377+
if(S_ISDIR(fdat.st_mode))
378+
tps[i]=DIRECTORY;
379+
else if(S_ISREG(fdat.st_mode))
380+
tps[i]=NFILE;
381+
else
382+
tps[i]=CSLOCOTHER;
383+
goto redirect;
384+
}
385+
else
386+
fprintf(stderr, "Could not stat %s.\n", subdir);
387+
}
352388
}
353-
else
354-
fprintf(stderr, "Could not stat %s.\n", subdir);
355389
}
390+
free(names[i]);
356391
}
357392

358393
free(names);
359394
free(tps);
360395
free(currf);
361396
}
362397
free(stack);
398+
if(apath)
399+
free(apath);
363400
if(CSLOC_ISSIF(ops))
364401
{
365402
csloc_sort_filen(CSLOC_ISSORT(ops), d, datsz);

csloc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct csloc_file_entry
2828
};
2929
typedef struct csloc_file_entry csloc_filen;
3030
typedef struct csloc_file_entry *csloc_filenp;
31+
int csloc____ispref(const char *pref, const char *str);
3132
int csloc____case_insensitive_strcmp(const char *xstr, const char *ystr);
3233
void csloc_sort_filen(int val, csloc_filenp arr, size_t sz);
3334
#ifdef _WIN32

main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#endif
1818
#include"csloc.h"
1919
#define VERSION_MINOR "8"
20-
#define VERSION_PATCH "2"
20+
#define VERSION_PATCH "3"
2121
int main(int argl,char*argv[])
2222
{
2323
if(argl==1)
@@ -31,7 +31,7 @@ int main(int argl,char*argv[])
3131
puts("-n to list the number before the path in -qs mode.");
3232
puts("-r to sort least to greatest.");
3333
puts("-f to count file size instead.");
34-
puts("-t to sort the files by number of lines.");
34+
puts("-t to sort the files by number of lines or size.");
3535
puts("-s to show the sloc of individual files.");
3636
puts("The options -r and -t automatically enable -s, -rs and -st are now redundant.");
3737
puts("-h to not count files beginning with a ., such files are considered hidden on linux.");

0 commit comments

Comments
 (0)