C - Unlink/Remove производит ошибку для имен файлов с пробелами

Я пытаюсь сделать функцию в C, чтобы стереть все содержимое временной папки и стереть папку.
Хотя я уже успешно создал код для циклического перемещения по файлам и удаления папки (это довольно просто), у меня возникают проблемы при удалении файлов с помощью unlink.
Вот код, который я использую:

int delete_folder(char *foldername) {
 DIR *dp;
 struct dirent *ep;
 dp=opendir(foldername);
 if (dp!=NULL) {
      readdir(dp); readdir(dp);
      while (ep=readdir(dp)) {
           char* cell = concatenate(concatenate(foldername, "\\"), "Bayesian Estimation.xlsx");//ep->d_name);
           printf("%s\n", cell);
           remove(cell);
           printf("%s\n", strerror(errno));

      }
      closedir(dp);
 }
 if (!rmdir(foldername)) {return(0);} else {return(-1);}
}

Код, который я написал, полностью функционален для всех файлов, кроме тех, которые содержат пробелы в имени файла. После некоторого тестирования я могу гарантировать, что функции отмены связи удаляют все файлы в папке (даже те, которые содержат специальные символы в имени файла), но не работают, если имя файла содержит пробел (однако, для этого же файла, если я удаляю пробел (s)), эта функция снова работает).

Кто-нибудь еще сталкивался с этой проблемой? И, что более важно, это может быть решено / обойдено?
(Проблема остается, даже если я введу последовательности выхода из космоса напрямую)
Ошибка, представленная unlink: "Нет такого файла или каталога" (ENOENT). Имейте в виду, что файл действительно находится в указанном месте (что можно проверить с помощью кода, выводящего правильное имя файла в ячейке переменной), и эта ошибка также возникает, если я использую функцию remove вместо unlink.

PS: функция concatenate - это моя собственная функция, которая выводит конкатенацию двух входных строк.

Изменить: код был написан в Codeblocks, в Windows.
Вот код для функции сцепления:

char* concatenate(char *str1, char *str2) {
 int a1 = strlen(str1), a2 = strlen(str2); char* str3[a1+a2+1];
 snprintf(str3, a1+a2+2, "%s%s", str1, str2);
 return(str3);
}

Несмотря на то, что вы правы, говоря, что это возможная (и простая) утечка памяти, входы и выходы функций генерируются кодом и предназначены только для личного использования, и, следовательно, нет серьезных оснований для беспокойства по этому поводу (нет реальной необходимости защищать от ошибок). код.)

2 ответа

Решение

Большое спасибо за ваш вклад, после того как я просмотрел ваши комментарии и сам провел несколько экспериментов, я понял, что удаление / отмена связи не работает, потому что имя файла только временно сохранялось в переменной ячейке (оно было там достаточно долго, чтобы правильно напечатано на консоли, отсюда и мое замешательство). После надлежащего сохранения моего имени файла перед использованием, моя проблема была полностью решена.
Вот код (я уже проверил его с именами файлов настолько сложными, насколько я мог их сделать):

int delete_folder(char* foldername) {
 DIR *dp;
 struct dirent *ep;
 dp=opendir(foldername);
 if (dp!=NULL) {
      readdir(dp); readdir(dp);
      while (ep=readdir(dp)) {
           char cell[strlen(foldername)+1+strlen(ep->d_name)+1];
           strcpy(cell, concatenate(concatenate(foldername, "\\"), ep->d_name));
           unlink(cell);
           printf("File \"%s\": %s\n", ep->d_name, strerror(errno));
      }
      closedir(dp);
 }
 if (!rmdir(foldername)) {return(0);} else {return(-1);}
}  

Я понимаю, что это была своего рода ошибка новичка, из-за того, что я немного потренировался в программировании на C, так что... Большое спасибо за вашу помощь!

Вы говорите, "используя unlink()"но код использует remove(), На какой ты платформе? Есть ли опасность, что ваша платформа реализует remove() запустив внешнюю команду, которая не обрабатывает пробелы в именах файлов должным образом? На большинстве систем это не будет проблемой.

Проблема в том, что вы не проверяете возвращаемое значение из remove() перед печатью ошибка. Вы должны печатать ошибку только в том случае, если функция указывает, что она вызвала ошибку. Нет функций в наборах библиотек Standard C (или POSIX) errno в ноль. Также об ошибках следует сообщать по стандартной ошибке; для этого предназначен стандартный поток ошибок.

if (remove(cell) != 0)
    fprintf(stderr, "Failed to remove %s (%d: %s)\n", cell, errno, strerror(errno));
else
    printf("%s removed OK\n", cell);

Я считаю else в качестве временной меры, пока вы работаете с кодом.

Выглядит так, как будто вы теряете память, как сито пословиц. Вы фиксируете результат операции двойного сцепления в cell, но ты никогда не освобождаешь это. Действительно, если оба вложенных вызова выделяют память, то вы получите утечку, даже если добавите free(cell); в конце цикла (внутри цикла, после второго printf()тот, который я деконструировал). Если concatenate() не выделяет новую память каждый раз (он возвращает указатель на статически выделенную память, тогда я думаю, что конкатенация строки с выводом concatenate() также опасно, вероятно вызывая неопределенное поведение, когда вы копируете строку поверх себя. Вы должны внимательно посмотреть на код для concatenate()и / или представить его для анализа.

Другие вопросы по тегам