Changeset 3192 for trunk/src/kmk/kmkbuiltin/ln.c
- Timestamp:
- Mar 26, 2018, 10:25:56 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/ln.c
r2466 r3192 61 61 #include "kmkbuiltin.h" 62 62 63 static int fflag; /* Unlink existing files. */ 64 static int hflag; /* Check new name for symlink first. */ 65 static int iflag; /* Interactive mode. */ 66 static int sflag; /* Symbolic, not hard, link. */ 67 static int vflag; /* Verbose output. */ 68 /* System link call. */ 69 static int (*linkf)(const char *, const char *); 70 static char linkch; 63 /********************************************************************************************************************************* 64 * Structures and Typedefs * 65 *********************************************************************************************************************************/ 66 typedef struct LNINSTANCE 67 { 68 PKMKBUILTINCTX pCtx; 69 int fflag; /* Unlink existing files. */ 70 int hflag; /* Check new name for symlink first. */ 71 int iflag; /* Interactive mode. */ 72 int sflag; /* Symbolic, not hard, link. */ 73 int vflag; /* Verbose output. */ 74 int (*linkf)(const char *, const char *); /* System link call. */ 75 char linkch; 76 } LNINSTANCE; 77 typedef LNINSTANCE *PLNINSTANCE; 78 71 79 static struct option long_options[] = 72 80 { … … 77 85 78 86 79 static int linkit( const char *, const char *, int);80 static int usage( FILE *);87 static int linkit(PLNINSTANCE,const char *, const char *, int); 88 static int usage(PKMKBUILTINCTX, int); 81 89 82 90 83 91 int 84 kmk_builtin_ln(int argc, char *argv[], char **envp) 85 { 92 kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 93 { 94 LNINSTANCE This; 86 95 struct stat sb; 87 96 char *sourcedir; … … 89 98 90 99 /* initialize globals. */ 91 fflag = hflag = iflag = sflag = vflag = 0; 92 linkch = 0; 93 linkf = NULL; 100 This.pCtx = pCtx; 101 This.fflag = 0; 102 This.hflag = 0; 103 This.iflag = 0; 104 This.sflag = 0; 105 This.vflag = 0; 106 This.linkch = 0; 107 This.linkf = NULL; 94 108 95 109 /* kmk: reset getopt() and set program name. */ 96 g_progname = argv[0];97 110 opterr = 1; 98 111 optarg = NULL; … … 103 116 switch (ch) { 104 117 case 'f': 105 fflag = 1;106 iflag = 0;118 This.fflag = 1; 119 This.iflag = 0; 107 120 break; 108 121 case 'h': 109 122 case 'n': 110 hflag = 1;123 This.hflag = 1; 111 124 break; 112 125 case 'i': 113 iflag = 1;114 fflag = 0;126 This.iflag = 1; 127 This.fflag = 0; 115 128 break; 116 129 case 's': 117 sflag = 1;130 This.sflag = 1; 118 131 break; 119 132 case 'v': 120 vflag = 1;133 This.vflag = 1; 121 134 break; 122 135 case 261: 123 usage( stdout);136 usage(pCtx, 0); 124 137 return 0; 125 138 case 262: … … 127 140 case '?': 128 141 default: 129 return usage( stderr);142 return usage(pCtx, 1); 130 143 } 131 144 … … 133 146 argc -= optind; 134 147 135 linkf =sflag ? symlink : link;136 linkch =sflag ? '-' : '=';148 This.linkf = This.sflag ? symlink : link; 149 This.linkch = This.sflag ? '-' : '='; 137 150 138 151 switch(argc) { 139 152 case 0: 140 return usage( stderr);153 return usage(pCtx, 1); 141 154 /* NOTREACHED */ 142 155 case 1: /* ln target */ 143 return linkit( argv[0], ".", 1);156 return linkit(&This, argv[0], ".", 1); 144 157 case 2: /* ln target source */ 145 return linkit( argv[0], argv[1], 0);158 return linkit(&This, argv[0], argv[1], 0); 146 159 default: 147 160 ; … … 149 162 /* ln target1 target2 directory */ 150 163 sourcedir = argv[argc - 1]; 151 if ( hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {164 if (This.hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) { 152 165 /* 153 166 * We were asked not to follow symlinks, but found one at … … 155 168 */ 156 169 errno = ENOTDIR; 157 return err( 1, "st_mode: %s", sourcedir);170 return err(pCtx, 1, "st_mode: %s", sourcedir); 158 171 } 159 172 if (stat(sourcedir, &sb)) 160 return err( 1, "stat: %s", sourcedir);173 return err(pCtx, 1, "stat: %s", sourcedir); 161 174 if (!S_ISDIR(sb.st_mode)) 162 return usage( stderr);175 return usage(pCtx, 1); 163 176 for (exitval = 0; *argv != sourcedir; ++argv) 164 exitval |= linkit( *argv, sourcedir, 1);177 exitval |= linkit(&This, *argv, sourcedir, 1); 165 178 return exitval; 166 179 } 167 180 168 181 static int 169 linkit( const char *target, const char *source, int isdir)182 linkit(PLNINSTANCE pThis, const char *target, const char *source, int isdir) 170 183 { 171 184 struct stat sb; … … 174 187 char path[PATH_MAX]; 175 188 176 if (! sflag) {189 if (!pThis->sflag) { 177 190 /* If target doesn't exist, quit now. */ 178 191 if (stat(target, &sb)) { 179 warn( "stat: %s", target);192 warn(pThis->pCtx, "stat: %s", target); 180 193 return (1); 181 194 } … … 183 196 if (S_ISDIR(sb.st_mode)) { 184 197 errno = EISDIR; 185 warn( "st_mode: %s", target);198 warn(pThis->pCtx, "st_mode: %s", target); 186 199 return (1); 187 200 } … … 194 207 if (isdir || 195 208 (lstat(source, &sb) == 0 && S_ISDIR(sb.st_mode)) || 196 (! hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) {209 (!pThis->hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) { 197 210 #if defined(_MSC_VER) || defined(__OS2__) 198 211 char *p2 = strrchr(target, '\\'); … … 210 223 (ssize_t)sizeof(path)) { 211 224 errno = ENAMETOOLONG; 212 warn( "snprintf: %s", target);225 warn(pThis->pCtx, "snprintf: %s", target); 213 226 return (1); 214 227 } … … 221 234 * and interactively if -i was specified. 222 235 */ 223 if ( fflag && exists) {236 if (pThis->fflag && exists) { 224 237 if (unlink(source)) { 225 warn( "unlink: %s", source);226 return (1); 227 } 228 } else if ( iflag && exists) {238 warn(pThis->pCtx, "unlink: %s", source); 239 return (1); 240 } 241 } else if (pThis->iflag && exists) { 229 242 fflush(stdout); 230 243 fprintf(stderr, "replace %s? ", source); … … 234 247 ch = getchar(); 235 248 if (first != 'y' && first != 'Y') { 236 fprintf(stderr, "not replaced\n");249 kmk_builtin_ctx_printf(pThis->pCtx, 1, "not replaced\n"); 237 250 return (1); 238 251 } 239 252 240 253 if (unlink(source)) { 241 warn( "unlink: %s", source);254 warn(pThis->pCtx, "unlink: %s", source); 242 255 return (1); 243 256 } … … 245 258 246 259 /* Attempt the link. */ 247 if ((* linkf)(target, source)) {248 warn( "%s: %s",linkf == link ? "link" : "symlink", source);260 if ((*pThis->linkf)(target, source)) { 261 warn(pThis->pCtx, "%s: %s", pThis->linkf == link ? "link" : "symlink", source); 249 262 return (1); 250 263 } 251 if ( vflag)252 (void)printf("%s %c> %s\n", source,linkch, target);264 if (pThis->vflag) 265 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s %c> %s\n", source, pThis->linkch, target); 253 266 return (0); 254 267 } 255 268 256 269 static int 257 usage(FILE *pf) 258 { 259 fprintf(pf, "usage: %s [-fhinsv] source_file [target_file]\n" 260 " or: %s [-fhinsv] source_file ... target_dir\n" 261 " or: %s source_file target_file\n" 262 " or: %s --help\n" 263 " or: %s --version\n", 264 g_progname, g_progname, g_progname, g_progname, g_progname); 270 usage(PKMKBUILTINCTX pCtx, int fIsErr) 271 { 272 kmk_builtin_ctx_printf(pCtx,fIsErr, 273 "usage: %s [-fhinsv] source_file [target_file]\n" 274 " or: %s [-fhinsv] source_file ... target_dir\n" 275 " or: %s source_file target_file\n" 276 " or: %s --help\n" 277 " or: %s --version\n", 278 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 279 pCtx->pszProgName, pCtx->pszProgName); 265 280 return 1; 266 281 } 282 283 #ifdef KMK_BUILTIN_STANDALONE 284 int main(int argc, char **argv, char **envp) 285 { 286 KMKBUILTINCTX Ctx = { "kmk_ln", NULL }; 287 return kmk_builtin_ln(argc, argv, envp, &Ctx); 288 } 289 #endif 290
Note:
See TracChangeset
for help on using the changeset viewer.