| /* --COPYRIGHT--,EPL |
| *Copyright (c) 2008 Texas Instruments and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Texas Instruments - initial implementation |
| * |
| * --/COPYRIGHT--*/ |
| /* |
| * ======== xdcrmp.c ======== |
| * Remove all package files in the specified base directories _except_ any |
| * "nested packages". |
| * |
| * usage: xdcrmp [-help] [-k] [-n] [base-directory ...] |
| */ |
| #include <xdc/std.h> |
| #include <xdc/services/host/lib/xutl.h> |
| #include <xdc/services/host/lib/lst.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #define MAXPATHLEN 1024 |
| |
| static Char pathBuf[MAXPATHLEN + 1]; |
| |
| static String usage = "%s: [-help] [-k] [-n] [package-base-directory ...]\n" |
| " -help display this message\n" |
| " -k keep all underlying packages. Without this flag,\n" |
| " only packages with the same repository are retained; \n" |
| " normally, packages contained in subdirectories are\n" |
| " removed unless they have exactly the same repository as\n" |
| " the package being removed.\n" |
| " -n don't actually remove any files; just show the commands\n" |
| " that would be executed.\n"; |
| |
| static String progName = NULL; |
| |
| static LST_Seq curDirList = NULL; |
| static LST_Seq curPkgBaseList = NULL; |
| static String curRepo = NULL; |
| static String curBase = NULL; |
| static String curName = NULL; |
| static Int curBaseLen = 0; |
| |
| static Bool kflag = FALSE; |
| static Bool nflag = FALSE; |
| |
| static int exitStatus = 0; |
| |
| static Int compare(const void *a, const void *b); |
| static Void deleteList(LST_Seq list); |
| static Bool filter(IArg arg, String baseName, String dirName, Char *end); |
| static Void rmDirs(LST_Seq dirs, LST_Seq pkgs); |
| static Int scanFile(IArg arg, IArg *cookie, String baseName, String dirName); |
| |
| /* |
| * ======== main ======== |
| */ |
| Int main(Int argc, String argv[]) |
| { |
| Int i; |
| |
| XUTL_init(); |
| LST_init(); |
| |
| progName = argv[0]; |
| |
| for (i = 1; i < argc; i++) { |
| if (argv[i][0] == '-') { |
| switch (argv[i][1]) { |
| case 'k': { |
| kflag = TRUE; |
| break; |
| } |
| case 'n': { |
| nflag = TRUE; |
| break; |
| } |
| case 'h': { |
| printf(usage, progName); |
| return (0); |
| } |
| default: { |
| fprintf(stderr, usage, progName); |
| return (1); |
| } |
| } |
| } |
| else { |
| break; |
| } |
| } |
| |
| if (i >= argc) { |
| fprintf(stderr, usage, progName); |
| return (1); |
| } |
| |
| for (; i < argc; i++) { |
| if (XUTL_isPackageBase(argv[i], FALSE)) { |
| |
| curDirList = LST_create(sizeof(String)); |
| curPkgBaseList = LST_create(sizeof(String)); |
| if (curDirList == NULL || curPkgBaseList == NULL) { |
| fprintf(stderr, "%s: output memory\n", progName); |
| exit(1); |
| } |
| |
| curRepo = NULL; |
| curBase = argv[i]; |
| curBaseLen = strlen(curBase); |
| |
| /* if argv[i] is a package base, find it's files */ |
| if ((curName = XUTL_getPackageName(curBase, FALSE)) != NULL) { |
| Char *cp; |
| /* replace '.'s with '/'s in curName */ |
| for (cp = curName; *cp != '\0'; cp++) { |
| if (*cp == '.') { |
| *cp = '/'; |
| } |
| } |
| |
| /* if we only keep pkgs with the same repo, compute it now */ |
| if (kflag == FALSE) { |
| curRepo = XUTL_getPackageRep(curBase); |
| } |
| |
| /* now scan the file system and remove pkg files */ |
| XUTL_scanFS(curBase, scanFile, filter, 0, XUTL_FSALL); |
| |
| free(curName); |
| if (curRepo != NULL) { |
| free(curRepo); |
| } |
| |
| /* remove the now empty directories */ |
| rmDirs(curDirList, curPkgBaseList); |
| deleteList(curDirList); |
| deleteList(curPkgBaseList); |
| } |
| } |
| else { |
| fprintf(stderr, "%s: %s is not a package base directory\n", |
| progName, argv[i]); |
| } |
| } |
| |
| return (exitStatus); |
| } |
| |
| /* |
| * ======== compare ======== |
| * Sort array so that prefixes appear later; this allows one to |
| * remove directories in order from 0 to N. |
| */ |
| static Int compare(const void *a, const void *b) |
| { |
| String dirA = *(String *)a; |
| String dirB = *(String *)b; |
| return (strcmp(dirB, dirA)); |
| } |
| |
| /* |
| * ======== deleteList ======== |
| */ |
| static void deleteList(LST_Seq list) |
| { |
| String name; |
| |
| for (LST_scan(list, &name); LST_next(list);) { |
| free(name); |
| } |
| |
| LST_delete(list); |
| } |
| |
| /* |
| * ======== filter ======== |
| * skip nested package directories |
| * |
| * Return TRUE to skip dirName/baseName (and not remove it), FALSE to |
| * scan it (i.e, remove it). |
| */ |
| static Bool filter(IArg arg, String baseName, String dirName, Char *end) |
| { |
| Int len = end - dirName; |
| Int baseLen = strlen(baseName); |
| Bool result = TRUE; |
| Bool isDir = FALSE; |
| |
| /* append baseName and dirName to determine if it's a package */ |
| if ((len + 1 + baseLen + 1) < MAXPATHLEN) { |
| sprintf(pathBuf, "%s/%s", dirName, baseName); |
| result = XUTL_isPackageBase(pathBuf, FALSE); |
| isDir = result ? TRUE : XUTL_isDir(pathBuf); |
| |
| /* if -k is not set, check curRepo against pathBuf pkg's repository */ |
| if (result && curRepo != NULL) { |
| String rname = XUTL_getPackageRep(pathBuf); |
| result = FALSE; /* only skip if curRepo matches pathBuf's repo */ |
| if (rname != NULL) { |
| if (strcmp(rname, curRepo) == 0) { |
| result = TRUE; |
| } |
| free(rname); |
| } |
| } |
| } |
| else { |
| fprintf(stderr, "%s: error: path too long (%s/%s)\n", |
| progName, dirName, baseName); |
| } |
| |
| #if 0 |
| printf("%s/%s: %s\n", dirName, baseName, |
| result == TRUE ? "TRUE" : "FALSE"); |
| #endif |
| |
| if (isDir) { |
| String tmp = strdup(pathBuf); |
| if (tmp == NULL |
| || LST_append(result ? curPkgBaseList:curDirList, &tmp) == FALSE) { |
| fprintf(stderr, "%s: error: out of memory\n", progName); |
| exit(1); |
| } |
| /* printf("appending %s (%s) ...\n", tmp, result ? "TRUE" : "FALSE");*/ |
| } |
| |
| return (result); |
| } |
| |
| /* |
| * ======== rmDirs ======== |
| */ |
| static Void rmDirs(LST_Seq dirs, LST_Seq pkgs) |
| { |
| Int dirTabLen = LST_length(dirs); |
| if (dirTabLen > 0) { |
| String pkg; |
| String dir; |
| Bool remove = TRUE; |
| Int dirIndex = 0; |
| Int i; |
| String *dirTab = (String *)malloc(dirTabLen * sizeof(String)); |
| if (dirTab == NULL) { |
| fprintf(stderr, "%s: error: out of memory\n", progName); |
| exit(1); |
| } |
| |
| for (LST_scan(dirs, &dir); LST_next(dirs);) { |
| /* if any pkg is under dir, don't remove it */ |
| for (LST_scan(pkgs, &pkg); LST_next(pkgs);) { |
| if (strncmp(dir, pkg, strlen(dir)) == 0) { |
| /* printf("preserving %s\n", dir); */ |
| remove = FALSE; |
| } |
| } |
| |
| if (remove == TRUE) { |
| dirTab[dirIndex++] = dir; |
| } |
| } |
| |
| /* sort directories so we can remove them from the bottom up */ |
| qsort(dirTab, dirIndex, sizeof(String), compare); |
| for (i = 0; i < dirIndex; i++) { |
| if (nflag == TRUE) { |
| printf("rmdir %s\n", dirTab[i]); |
| } |
| else { |
| if (!XUTL_rm(dirTab[i])) { |
| fprintf(stderr, "%s: can't remove '%s'\n", |
| progName, dirTab[i]); |
| exitStatus = 1; |
| } |
| } |
| } |
| |
| free(dirTab); |
| } |
| } |
| |
| /* |
| * ======== scanFile ======== |
| * remove file visited |
| */ |
| static Int scanFile(IArg arg, IArg *cookie, String baseName, String dirName) |
| { |
| if ((strlen(dirName) + strlen(baseName) + 1) < MAXPATHLEN) { |
| sprintf(pathBuf, "%s/%s", dirName, baseName); |
| if (nflag == TRUE) { |
| printf("rm %s\n", pathBuf); |
| } |
| else { |
| if (!XUTL_rm(pathBuf)) { |
| fprintf(stderr, "%s: can't remove '%s'\n", |
| progName, pathBuf); |
| exitStatus = 1; |
| } |
| } |
| } |
| return (0); |
| } |
| |