03-17-2015 08:54 AM
Hi,
I want to create directory in CVI. did not know that C does not have a native function for it. I tried this code (with some built-in error checks) but it seems to have some errors:
int Folder_Make (char Folder[])
{
//this function takes in argument with single forward slash(es) (FS),
//replaces them with double FS, then try to create intended folder
int result = 0;
int len_Folder = strlen (Folder);
int len_New;
int FS_count = 0;
int FS_last = 0; //last FS flag
int FS_max = 5; //max FS
int FS_pos [FS_max];
char *MyFolder;
//count FS
for (int i = 0; i < len_Folder; i++)
{
if (Folder [i] == '\\')
{
FS_pos [FS_count] = i; //FS position
FS_count++; //FS count
}
}
//add last FS if necessary
if (Folder [len_Folder - 1] != '\\') FS_last = 1;
if ((FS_last) && (FS_count < FS_max))
{
FS_pos [FS_count] = len_Folder; //FS position
FS_count++;
}
//check for consecutive FS prior to correction
for (int i = 0; i < (FS_count - 1); i++)
{
if (FS_pos [i] == FS_pos [i + 1]) result = -1;
}
if (!result) //still no error
{
len_New = len_Folder + FS_count; if (FS_last) len_New++;
MyFolder = malloc (len_New + 1);
for (int i = 0, j = 0; i < len_Folder; i++, j++)
{
MyFolder [j] = Folder [i];
if (Folder [i] == '\\')
{ j++;
MyFolder [j] = '\\';
}
if (i == len_Folder - 1)
{ j++;
MyFolder [j] = '\\';
if (FS_last)
{ j++;
MyFolder [j] = '\\';
}
}
}
MyFolder [len_New] = '\0'; //null-termination
}
//create folder
MakeDir (MyFolder);
return result;
/* error value
-1 consecutive FS found
*/
}
please help.
03-17-2015 09:46 AM
alright,
this code works, and it seems to be a more robust one.
int Folder_Make (char Folder[])
{
//this function takes in argument with single forward slash(es) (FS),
//replaces them with double FS, then try to create intended folder
int result = 0;
int len_Folder = strlen (Folder);
int len_A;
int FS_count = 0;
int FS_last = 0; //last FS flag
char *Folder_A;
//count FS (1)
for (int i = 0; i < len_Folder; i++)
{
if (Folder [i] == '\\') FS_count++; //FS count
}
//add last FS if necessary
if (Folder [len_Folder - 1] != '\\') FS_last = 1;
if (FS_last) FS_count++;
int FS_pos [FS_count];
FS_count = 0; //FS count reset
//count FS (2)
for (int i = 0; i < len_Folder; i++)
{
if (Folder [i] == '\\')
{
FS_pos [FS_count] = i; //FS position
FS_count++; //FS count
}
}
if (FS_last) FS_count++; //repeat due to FS_count reset
//check for consecutive FS prior to correction
for (int i = 0; i < (FS_count - 1); i++)
{
if (FS_pos [i] == FS_pos [i + 1]) result = -1;
}
if (!result) //still no error
{
len_A = len_Folder + FS_count; if (FS_last) len_A++;
Folder_A = malloc (len_A + 1);
for (int i = 0, j = 0; i < len_Folder; i++, j++)
{
Folder_A [j] = Folder [i];
if (Folder [i] == '\\') { j++; Folder_A [j] = '\\'; }
if (i == len_Folder - 1)
{ j++; Folder_A [j] = '\\';
if (FS_last) { j++; Folder_A [j] = '\\'; }
}
}
Folder_A [len_A] = '\0'; //null-termination
//count FS_2 (1)
int len_Corrected = strlen (Folder_A);
int FS_count_2 = 0;
int FS_pos_2 [FS_count * 2];
//check if path length is legible (260 max w/ null char)
if ((len_Corrected + 1) >= 260) result = -2;
if (!result) //still no error
{
//count FS
for (int i = 0; i < len_Corrected; i++)
{
if (Folder_A [i] == '\\')
{
FS_pos_2 [FS_count_2] = i; //FS position 2
FS_count_2++; //FS count 2
}
}
//recursively check and create folders
char Folder_B [260]; //standard = 260 max char. w/ null char
int a, b, c, d, x; //place holders
SetBreakOnLibraryErrors (0); //turn OFF alarm
//copy string and recursively create folder
for (int i = 3; i < FS_count_2; i++)
{
memmove (Folder_B, Folder_A, FS_pos_2 [i] + 1);
Folder_B [FS_pos_2 [i] + 1] = '\0';
x = GetFileAttrs (Folder_B, &a, &b, &c, &d);
if (x != 1) //not directory or not exist
{
result = MakeDir (Folder_B);
}
}
SetBreakOnLibraryErrors (1); //turn ON alarm
}
}
return result;
/* error value
-1 consecutive FS found
-2 len_Corrected + 1 >= 260 (max)
*/
}
please correct any error you may find.
03-18-2015 04:58 AM - edited 03-18-2015 05:01 AM
I personally would take another approach: it adds some more preliminary checks with respect to your code and operates a different way.
//---------------------------------------------------------------------- // Function MyCreateFolder () // // Missing: get active drive and pathname and restore at function end //---------------------------------------------------------------------- /// HIFN MyCreateFolder () /// HIFN Creation of a pathname or a series of folders. /// HIFN The function takes a string in input, checks whether it is a /// HIFN valid pathname and creates necessary folders to obtain the /// HIFN desired path on disk.
/// HIFN /// HIFN The function changes active drive/folder to the new path /// HIFN /// HIPAR pathname/The pathname containing the folder(s) to be created
/// HIPAR pathname/It must be a valid, absolute pathname including
/// HIPAR pathname/the drive letter /// HIRET Errors returned from MkDir. /// HIRET Errors from other functions are mapped to those error codes. int MyCreateFolder (char *pathname) { int ro, hid, sys, arc, drv, ndrv; int result = 0; char *token; char pattern[16] = "\042.:<>|*?/"; // characters not allowed in file/folder names char drive[MAX_DRIVENAME_LEN], file[MAX_PATHNAME_LEN]; DebugPrintf ("Original string supplied: %s\n", pathname); // 1. Check for pathname lenght if (strlen (pathname) > MAX_PATHNAME_LEN) { MessagePopup ("Error", "Too longh pathname supplied."); result = -5; goto Error; } // 2. Separate pathname path from disk name SplitPath (pathname, drive, pathname, file); MakePathname (pathname, file, pathname); // Rebuild complete pathname DebugPrintf ("Pathname extracted: %s\n", pathname); // 3. Check drive name if (!strlen (drive)) { MessagePopup ("Error", "Pathname must include a drive name."); result = -5; goto Error; } StringUpperCase (drive); // 4. Check for forbidden characters in pathname if (strcspn (pathname, pattern) < strlen (pathname)) { MessagePopup ("Error", "Characters not allowed in pathname."); result = -5; goto Error; } // 5. Change active drive if needed GetDrive (&drv, &ndrv); if (drv != (drive[0] - 65)) { if (SetDrive (drive[0] - 65) < 0) { MessagePopup ("Error", "Error changing to target drive."); result = -3; goto Error; } } // Move to drive radix SetDir ("\\"); // 6. Separate path components and create folders if needed token = strtok (pathname, "\\"); while (token) { DebugPrintf ("pathname: %s\n", token); // Check if the pathname is to be created switch (GetFileAttrs (token, &ro, &hid, &sys, &arc)) { case 1: // Specified file is a directory -> skip break; case 0: // Success: a file with the given name exists -> error result = -9; goto Error; case -1: // File not found -> create directory if (result = MakeDir (token) < 0) { MessagePopup ("Error", "Error creating directory."); goto Error; } break; } // Move to the new folder SetDir (token); // Check for next folder in path token = strtok (NULL, "\\"); } Error: return result; }
Whichever is the solution you adopt, the use of MAX_PATHNAME_LEN and MAX_FILENAME_LEN macros makes your code more adaptive to OS changes.