Вы не выделяете достаточно места для строки.
Вы делаете неортодоксальный расчет длины, который игнорирует фактическую длину mydir;затем вы делаете хорошую копию имени каталога (но теряете память, ранее выделенную);Затем вы объединяете имя в конце пробела, выделенного strdup()
, что всегда плохо.Если вы пропустили sizeof()
, то вы бы выделяли на один байт слишком мало для строки каталога с нулевым символом в конце.
Вам также не следует кэшировать отдельные возвращаемые значения из readdir()
, поскольку обычно он возвращает указатель наодин и тот же бит памяти каждый раз.Вы, конечно, не имеете права предполагать, что это происходит иначе.
Вы также попираете освобожденную память, если действительно выпускаете buf внутри цикла;Вы выделяете только один раз и освобождаетесь много раз.
Обычно вы вообще не удосужились бы выделить buf
;это не такая большая структура.
У вас также нет очевидного разделителя косой черты между именем каталога и компонентом имени файла;это может не иметь значения, если вы убедитесь, что у mydir
есть один в конце.
Вот простая программа, которая более или менее делает то, что необходимо.
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
static const char mydir[] = "./";
DIR *dirh;
size_t dlen = strlen(mydir) + 1;
if ((dirh = opendir(mydir)) != 0)
{
struct dirent *dirp;
while ((dirp = readdir(dirh)) != 0)
{
char *str = malloc(dlen + strlen(dirp->d_name));
if (str != 0)
{
struct stat buf;
strcpy(str, mydir);
strcat(str, dirp->d_name);
if (stat(str, &buf) == 0)
{
struct passwd *pwd = getpwuid(buf.st_uid);
if (pwd != 0)
printf("\t%s (%s)\n", str, pwd->pw_name);
}
free(str);
}
}
closedir(dirh);
}
return 0;
}
Примечание: Вычисление dlen
является правильным, но только потому, что значение mydir
включает косую черту.Если имя каталога не включает этот завершающий слеш, для кода потребуются изменения в расчете длины и форматировании составного имени (последовательность strcpy()
strcat()
).Осторожно!