示例#1
0
/*
 * Create all the directories in the given path.  Path must be non-const.  Trailing '/' characters are removed.
 */
int bpc_path_create(char *path)
{
    char *p = path;
    STRUCT_STAT st;
    int levels = 0;

    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_create(%s)\n", path);
    /*
     * check if it exists already
     */
    if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) return 0;

    /*
     * We walk up until we find the deepest level directory that exists.
     * First remove trailing slashes.
     */
    p = path + strlen(path);
    while ( p > path && p[-1] == '/' ) p--;
    if ( *p == '/' ) *p = '\0';
    while ( p > path ) {
        while ( p > path && p[-1] != '/' ) p--;
        while ( p > path && p[-1] == '/' ) p--;
        if ( *p == '/' ) {
            *p = '\0';
            levels++;
            if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) break;
        }
    }
    if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_create: found that %s exists (%d levels up)\n", path, levels);

    /*
     * We have removed levels '/' characters from path.  Replace each one and create the directory.
     */
    while ( levels-- > 0 ) {
        p = path + strlen(path);
        *p = '/';
        if ( mkdir(path, ACCESSPERMS) < 0 && errno != EEXIST) {
            bpc_logErrf("bpc_path_create: can't create %s (errno %d)\n", path, errno);
            return -1;
        }
        if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_create: created %s\n", path);
    }
    return 0;
}
示例#2
0
/*
 * Given a backup path, split it into the directory, file name, and path to the directory (starting
 * with the share name, ie: relative to ac->backupTopDir).
 *
 * splitPath will strip initial "./" and trailing "/." or "/" before splitting the path, but isn't
 * capable of handling paths with "/." in the middle, or ".." anywhere.
 */
static void splitPath(bpc_attribCache_info *ac, char *dir, char *fileName, char *attribPath, char *path)
{
    char *dirOrig = dir;
    char fullPath[BPC_MAXPATHLEN];
    size_t pathLen;

    /*
     * remove initial "./"
     */
    while ( path[0] == '.' && path[1] == '/' ) {
        path += 2;
        while ( path[0] == '/' ) path++;
    }

    /*
     * if this is a relative path, prepend ac->currentDir (provided ac->currentDir is set)
     */
    if ( path[0] != '/' && ac->currentDir[0] ) {
        snprintf(fullPath, BPC_MAXPATHLEN, "%s/%s", ac->currentDir, path);
        path = fullPath;
    }

    /*
     * strip trailing "/." or "/" 
     */
    pathLen = strlen(path);
    while ( (pathLen > 1 && path[pathLen - 2] == '/' && path[pathLen - 1] == '.')
         || (pathLen > 0 && path[pathLen - 1] == '/') ) {
        if ( path != fullPath ) {
            strncpy(fullPath, path, BPC_MAXPATHLEN);
            path = fullPath;
        }
        if ( path[pathLen - 1] == '/' ) {
            pathLen -= 1;
        } else {
            pathLen -= 2;
        }
        path[pathLen] = '\0';
        if ( BPC_LogLevel >= 9 ) bpc_logMsgf("splitPath: trimming path = '%s'\n", path);
    }
    if ( !path[0] || (!path[1] && (path[0] == '.' || path[0] == '/')) ) {
        strcpy(fileName, ac->shareNameUM);
        strcpy(dir,  "/");
        strcpy(attribPath, "/attrib");
    } else {
        char *p;
        int dirLen = BPC_MAXPATHLEN - ac->shareNameLen;

        strcpy(dir, ac->shareName);
        dir += strlen(dir);
        if ( (p = strrchr(path, '/')) ) {
            if ( *path != '/' ) {
                *dir++ = '/'; dirLen--;
                *dir = '\0';
            }
            strcpy(fileName, p+1);
            *p = '\0';
            bpc_fileNameMangle(dir, dirLen, path);
            *p = '/';
        } else {
            strcpy(fileName, path);
        }
        snprintf(attribPath, BPC_MAXPATHLEN, "%s/attrib", dirOrig);
    }
    if ( BPC_LogLevel >= 9 ) bpc_logMsgf("splitPath: returning dir = '%s', fileName = '%s', attrib = '%s' from path = '%s'\n",
                            dirOrig, fileName, attribPath, path);
}
示例#3
0
/*
 * Remove all the files below path (if a directory) and path itself.  Deduct reference counts
 * for every attrib file removed.
 *
 * Note that inodes are *not* updated, even in cases where nlinks > 0.
 */
int bpc_path_remove(char *path, int compress)
{
    char filePath[BPC_MAXPATHLEN];
    STRUCT_STAT st;
    DIR *dir;
    struct dirent *dp;
    int errorCnt = 0;
    size_t dirListSize = 0, dirListLen = 0;
    char *dirList = NULL, *dirListP;

    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_remove(%s)\n", path);
    if ( !(dir = opendir(path)) ) {
        unlink(path);
        return errorCnt;
    }
    while ( (dp = readdir(dir)) ) {
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue;
        snprintf(filePath, sizeof(filePath), "%s/%s", path, dp->d_name);
        if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_remove: removing %s\n", filePath);
        if ( stat(filePath, &st) ) {
            /*
             * hmmm.  stat failed - just try to remove it
             */
            unlink(filePath);
            continue;
        }
        if ( S_ISDIR(st.st_mode) ) {
            /*
             * To avoid recursing with dir still open (consuming an open fd), remember all the dirs
             * and recurse after we close dir.
             */
            if ( !dirList ) {
                dirListSize = 4096;
                if ( !(dirList = malloc(dirListSize)) ) {
                    bpc_logErrf("bpc_path_refCountAll: can't allocate %u bytes\n", (unsigned)dirListSize);
                    return ++errorCnt;
                }
            }
            if ( dirListLen + strlen(dp->d_name) + 1 >= dirListSize ) {
                dirListSize = dirListSize * 2 + strlen(dp->d_name);
                if ( !(dirList = realloc(dirList, dirListSize)) ) {
                    bpc_logErrf("bpc_path_refCountAll: can't reallocate %u bytes\n", (unsigned)dirListSize);
                    return ++errorCnt;
                }
            }
            strcpy(dirList + dirListLen, dp->d_name);
            dirListLen += strlen(dp->d_name) + 1;
        } else {
            /*
             * if this is an attrib file, we need to read it and deduct the reference counts.
             */
            if ( !strncmp(dp->d_name, "attrib", 6) ) {
                bpc_attrib_dir dir;

                bpc_attrib_dirInit(&dir, compress);
                if ( bpc_attrib_dirRead(&dir, NULL, filePath, 0) ) {
                    bpc_logErrf("bpc_path_remove: can't read attrib file %s\n", filePath);
                    errorCnt++;
                }
                if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_remove: adjusting ref counts from attrib file %s\n", filePath);
                if ( !unlink(filePath) ) {
                    /*
                     * Only reduce the ref counts if we succeeded in removing the attrib file
                     */
                    bpc_attrib_dirRefCount(&dir, -1);
                }
                bpc_attrib_dirDestroy(&dir);
            } else {
                if ( unlink(filePath) ) errorCnt++;
            }
        }
    }
    closedir(dir);
    /*
     * Now visit the subdirs we have saved above.
     */
    if ( dirList ) {
        for ( dirListP = dirList ; dirListP < dirList + dirListLen ; dirListP += strlen(dirListP) + 1 ) {
            snprintf(filePath, sizeof(filePath), "%s/%s", path, dirListP);
            errorCnt += bpc_path_remove(filePath, compress);
        }
        free(dirList);
    }
    if ( rmdir(path) ) errorCnt++;
    return errorCnt;
}