[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [55127] trunk/blender/source/blender/ blenlib/intern/fileops.c: patch [#34103] fileops_recursive_operation.patch
Campbell Barton
ideasman42 at gmail.com
Sat Mar 9 10:38:28 CET 2013
Revision: 55127
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=55127
Author: campbellbarton
Date: 2013-03-09 09:38:27 +0000 (Sat, 09 Mar 2013)
Log Message:
-----------
patch [#34103] fileops_recursive_operation.patch
from Lawrence D'Oliveiro (ldo)
Fix potential memory leaks in recursive_operation while simplifying cleanup logic.
Modified Paths:
--------------
trunk/blender/source/blender/blenlib/intern/fileops.c
Modified: trunk/blender/source/blender/blenlib/intern/fileops.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/fileops.c 2013-03-09 07:17:35 UTC (rev 55126)
+++ trunk/blender/source/blender/blenlib/intern/fileops.c 2013-03-09 09:38:27 UTC (rev 55127)
@@ -282,6 +282,7 @@
return err;
}
+/* Not used anywhere! */
int BLI_move(const char *file, const char *to)
{
int err;
@@ -401,8 +402,9 @@
#else /* The UNIX world */
+/* results from recursive_operation and its callbacks */
enum {
- /* operation succeeded succeeded */
+ /* operation succeeded */
RecursiveOp_Callback_OK = 0,
/* operation requested not to perform recursive digging for current path */
@@ -437,121 +439,123 @@
return result;
}
-static int recursive_operation(const char *startfrom, const char *startto, RecursiveOp_Callback callback_dir_pre,
+
+
+/**
+ * Scans \a startfrom, generating a corresponding destination name for each item found by
+ * prefixing it with startto, recursively scanning subdirectories, and invoking the specified
+ * callbacks for files and subdirectories found as appropriate.
+ *
+ * \param startfrom Top-level source path.
+ * \param startto Top-level destination path.
+ * \param callback_dir_pre Optional, to be invoked before entering a subdirectory, can return
+ * RecursiveOp_Callback_StopRecurs to skip the subdirectory.
+ * \param callback_file Optional, to be invoked on each file found.
+ * \param callback_dir_post optional, to be invoked after leaving a subdirectory.
+ * \return
+ */
+static int recursive_operation(const char *startfrom, const char *startto,
+ RecursiveOp_Callback callback_dir_pre,
RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post)
{
- struct dirent **dirlist;
struct stat st;
char *from = NULL, *to = NULL;
char *from_path = NULL, *to_path = NULL;
+ struct dirent **dirlist = NULL;
size_t from_alloc_len = -1, to_alloc_len = -1;
int i, n, ret = 0;
- /* ensure there's no trailing slash in file path */
- from = strip_last_slash(startfrom);
- if (startto)
- to = strip_last_slash(startto);
+ do { /* once */
+ /* ensure there's no trailing slash in file path */
+ from = strip_last_slash(startfrom);
+ if (startto)
+ to = strip_last_slash(startto);
- ret = lstat(from, &st);
- if (ret < 0) {
- /* source wasn't found, nothing to operate with */
- return ret;
- }
+ ret = lstat(from, &st);
+ if (ret < 0)
+ /* source wasn't found, nothing to operate with */
+ break;
- if (!S_ISDIR(st.st_mode)) {
- /* source isn't a directory, can't do recursive walking for it,
- * so just call file callback and leave */
- if (callback_file) {
- ret = callback_file(from, to);
+ if (!S_ISDIR(st.st_mode)) {
+ /* source isn't a directory, can't do recursive walking for it,
+ * so just call file callback and leave */
+ if (callback_file != NULL) {
+ ret = callback_file(from, to);
+ if (ret != RecursiveOp_Callback_OK)
+ ret = -1;
+ }
+ break;
+ }
- if (ret != RecursiveOp_Callback_OK)
- ret = -1;
+ n = scandir(startfrom, &dirlist, 0, alphasort);
+ if (n < 0) {
+ /* error opening directory for listing */
+ perror("scandir");
+ ret = -1;
+ break;
}
- MEM_freeN(from);
- if (to) MEM_freeN(to);
-
- return ret;
- }
-
-
- n = scandir(startfrom, &dirlist, 0, alphasort);
- if (n < 0) {
- /* error opening directory for listing */
- perror("scandir");
-
- MEM_freeN(from);
- if (to) MEM_freeN(to);
-
- return -1;
- }
-
- if (callback_dir_pre) {
- /* call pre-recursive walking directory callback */
- ret = callback_dir_pre(from, to);
-
- if (ret != RecursiveOp_Callback_OK) {
- MEM_freeN(from);
- if (to) free(to);
-
- if (ret == RecursiveOp_Callback_StopRecurs) {
- /* callback requested not to perform recursive walking, not an error */
- return 0;
+ if (callback_dir_pre != NULL) {
+ ret = callback_dir_pre(from, to);
+ if (ret != RecursiveOp_Callback_OK) {
+ if (ret == RecursiveOp_Callback_StopRecurs)
+ /* callback requested not to perform recursive walking, not an error */
+ ret = 0;
+ else
+ ret = -1;
+ break;
}
-
- return -1;
}
- }
- for (i = 0; i < n; i++) {
- struct dirent *dirent = dirlist[i];
+ for (i = 0; i < n; i++) {
+ const struct dirent * const dirent = dirlist[i];
- if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) {
- free(dirent);
- continue;
- }
+ if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
+ continue;
- join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
+ join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
+ if (to)
+ join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
- if (to)
- join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
+ if (dirent->d_type == DT_DIR) {
+ /* recursively dig into a subfolder */
+ ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
+ }
+ else if (callback_file != NULL) {
+ ret = callback_file(from_path, to_path);
+ if (ret != RecursiveOp_Callback_OK)
+ ret = -1;
+ }
- if (dirent->d_type == DT_DIR) {
- /* recursively dig into a folder */
- ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
+ if (ret != 0)
+ break;
}
- else if (callback_file) {
- /* call file callback for current path */
- ret = callback_file(from_path, to_path);
- if (ret != RecursiveOp_Callback_OK)
- ret = -1;
- }
-
- if (ret != 0) {
- while (i < n) {
- free(dirlist[i++]);
- }
+ if (ret != 0)
break;
- }
- }
- free(dirlist);
-
- if (ret == 0) {
- if (callback_dir_post) {
- /* call post-recursive directory callback */
+ if (callback_dir_post != NULL) {
ret = callback_dir_post(from, to);
if (ret != RecursiveOp_Callback_OK)
ret = -1;
}
}
+ while (false);
- if (from_path) MEM_freeN(from_path);
- if (to_path) MEM_freeN(to_path);
+ if (dirlist != NULL) {
+ for (i = 0; i < n; i++) {
+ free(dirlist[i]);
+ }
+ free(dirlist);
+ }
+ if (from_path != NULL)
+ MEM_freeN(from_path);
+ if (to_path != NULL)
+ MEM_freeN(to_path);
+ if (from != NULL)
+ MEM_freeN(from);
+ if (to != NULL)
+ MEM_freeN(to);
- MEM_freeN(from);
- if (to) MEM_freeN(to);
-
return ret;
}
@@ -802,6 +806,9 @@
return RecursiveOp_Callback_OK;
}
+/* if *file represents a directory, moves all its contents into *to, else renames
+ * file itself to *to. */
+/* Not used anywhere! */
int BLI_move(const char *file, const char *to)
{
int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL);
More information about the Bf-blender-cvs
mailing list