スタック内に保存するパスは全て違うのですから struct st 毎に領域が必要なのに、全て path になってしまっています。
struct st のメンバ p は char ポインタではなく char 配列とし、 path の内容をコピーして保存することになるのでは無いでしょうか。(alloc してもいいですけど。)
struct st の要素の使い方よりも、全体的に妙なことになっています。
st.l が dirent 配列としても st.i は必要無いはずです。(dopen とか dread がどういうモノなのかはっきりしませんが。)
スタックにはパスだけあれば十分だと思います。
c
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <dirent.h>
5#include <sys/stat.h>
6
7typedef struct {
8 char path[512];
9} StackEntry;
10
11typedef struct {
12 int top;
13 int capa;
14 StackEntry **entries;
15} Stack;
16
17Stack *allocStack() {
18 Stack *stack = malloc(sizeof(Stack));
19 memset(stack, 0, sizeof(Stack));
20 return stack;
21}
22
23void freeStack(Stack *stack) {
24 if(stack != NULL) {
25 if(stack->entries != NULL) {
26 for(int i=0; i<stack->top; i++) freeEntry(stack->entries[i]);
27 free(stack->entries);
28 }
29 free(stack);
30 }
31}
32
33void pushStack(Stack *stack, StackEntry *entry) {
34 if(stack->top == stack->capa || stack->entries == NULL) {
35 int capa = stack->capa + 10;
36 StackEntry **p = realloc(stack->entries, sizeof(StackEntry *) * capa);
37 if(p == NULL) {
38 printf("pushStack: realloc error.");
39 exit(1);
40 }
41 stack->capa = capa;
42 stack->entries = p;
43 }
44 stack->entries[stack->top++] = entry;
45}
46
47StackEntry *popStack(Stack *stack) {
48 if(stack == NULL || stack->top == 0) return NULL;
49 return stack->entries[--stack->top];
50}
51
52StackEntry *allocEntry(char *path) {
53 StackEntry *entry = malloc(sizeof(StackEntry));
54 if(entry == NULL) {
55 printf("createEntry: malloc error.");
56 exit(1);
57 }
58 strcpy(entry->path, path);
59 return entry;
60}
61
62void freeEntry(StackEntry *entry) {
63 if(entry != NULL) free(entry);
64}
65
66int isDirectory(char *path) {
67 struct stat st;
68 if(stat(path, &st)) return 0; //false
69 return (st.st_mode & S_IFMT) == S_IFDIR;
70}
71
72void printdir(char *path){
73 if(!isDirectory(path)) {
74 printf("file: %s\n", path);
75 return;
76 }
77
78 Stack *stack = allocStack();
79 pushStack(stack, allocEntry(path));
80
81 for(StackEntry *parent; (parent=popStack(stack)) != NULL; freeEntry(parent)) {
82 printf("parent->path=%s\n", parent->path);
83 DIR *dir = opendir(parent->path);
84
85 for(struct dirent *de; (de=readdir(dir)) != NULL; ) {
86 printf("de->d_name=%s\n", de->d_name);
87 if(de->d_name[0] == '.') continue; //"."(カレント),".."(親)および'.'で始まる隠しファイルは無視
88
89 char childpath[1024];
90 sprintf(childpath, "%s\\%s", parent->path, de->d_name);
91 if(isDirectory(childpath)) {
92 printf("directory: %s\n", childpath);
93 pushStack(stack, allocEntry(childpath));
94 } else {
95 printf("file: %s\n", childpath);
96 }
97 }
98
99 closedir(dir);
100 }
101
102 freeStack(stack);
103}
104
105int main(int argc, char *argv[]) {
106 if(argc != 2) {
107 fprintf(stderr, "Usage: %s <directory-path>\n", argv[0]);
108 exit(1);
109 }
110 printdir(argv[1]);
111}
フォルダ構成

実行結果
plain
1> printdir F:\teratail\teratail\aaa
2parent->path=F:\teratail\teratail\aaa
3de->d_name=.
4de->d_name=..
5de->d_name=a1.txt
6file: F:\teratail\teratail\aaa\a1.txt
7de->d_name=a2.txt
8file: F:\teratail\teratail\aaa\a2.txt
9de->d_name=bbb
10directory: F:\teratail\teratail\aaa\bbb
11de->d_name=zzz
12directory: F:\teratail\teratail\aaa\zzz
13parent->path=F:\teratail\teratail\aaa\zzz
14de->d_name=.
15de->d_name=..
16de->d_name=z1.txt
17file: F:\teratail\teratail\aaa\zzz\z1.txt
18parent->path=F:\teratail\teratail\aaa\bbb
19de->d_name=.
20de->d_name=..
21de->d_name=b1.txt
22file: F:\teratail\teratail\aaa\bbb\b1.txt