/* flagdir.c - Novell FLAGDIR-like DOS utility, Client32 version */ #include "net.h" #include "c32ncp.h" #include #define FD_NWFA_H 0x00000002UL #define FD_NWFA_SY 0x00000004UL #define FD_NWFA_P 0x00010000UL #define FD_NWFA_RI 0x00020000UL #define FD_NWFA_DI 0x00040000UL #define FD_DIR_BITS (FD_NWFA_H | FD_NWFA_SY | FD_NWFA_P | FD_NWFA_RI | FD_NWFA_DI) #ifndef _A_RDONLY #define _A_RDONLY 0x01 #endif #ifndef _A_HIDDEN #define _A_HIDDEN 0x02 #endif #ifndef _A_SYSTEM #define _A_SYSTEM 0x04 #endif #ifndef _A_SUBDIR #define _A_SUBDIR 0x10 #endif #ifndef _A_ARCH #define _A_ARCH 0x20 #endif static int fd_same(char *a, char *b) { while (*a || *b) { int ca = *a++; int cb = *b++; if (ca >= 'a' && ca <= 'z') ca -= 32; if (cb >= 'a' && cb <= 'z') cb -= 32; if (ca != cb) return(0); } return(1); } static void fd_upcopy(char *dst, char *src, int max) { int i = 0; if (!src) src = ""; while (*src && i < max - 1) { char c = *src++; if (c == '/') c = '\\'; if (c >= 'a' && c <= 'z') c -= 32; dst[i++] = c; } dst[i] = 0; } static int fd_get_current_drive(void) { REGS regs; regs.h.ah = 0x19; int86(0x21, ®s, ®s); return((int)regs.h.al); } static int fd_current_dhandle(uint8 *dhandle) { uint8 connid = 0; uint8 flags = 0; int drive; drive = fd_get_current_drive(); if (get_drive_info((uint8)drive, &connid, dhandle, &flags)) return(-1); if (!connid || (flags & 0x80)) return(-1); return(0); } static int fd_current_prefix(char *out, int max) { uint8 connid = 0; uint8 dhandle = 0; uint8 flags = 0; int drive; char server[52]; char path[260]; char volume[32]; char *p; int i = 0; if (!out || max < 8) return(-1); out[0] = '\0'; drive = fd_get_current_drive(); if (get_drive_info((uint8)drive, &connid, &dhandle, &flags)) return(-1); if (!connid || (flags & 0x80)) return(-1); server[0] = '\0'; if (get_fs_name(connid, server)) server[0] = '\0'; path[0] = '\0'; if (get_dir_path(dhandle, path) || !path[0]) return(-1); p = strchr(path, ':'); if (!p) return(-1); while (path + i < p && i < (int)sizeof(volume) - 1) { volume[i] = path[i]; i++; } volume[i] = '\0'; if (!volume[0]) return(-1); if (server[0]) sprintf(out, "%s/%s:", server, volume); else sprintf(out, "%s:", volume); return(0); } static int fd_current_display_path(uint8 dhandle, char *out, int max) { char path[260]; char *p; if (!out || max < 2) return(-1); out[0] = '\0'; path[0] = '\0'; if (get_dir_path(dhandle, path) || !path[0]) return(-1); p = strchr(path, ':'); if (p) p++; else p = path; if (!*p) out[0] = '\0'; else strmaxcpy(out, p, max - 1); return(0); } static int fd_is_current_path(char *path) { if (!path || !*path) return(1); if (fd_same(path, ".")) return(1); if (fd_same(path, ".\\")) return(1); if (fd_same(path, "./")) return(1); return(0); } static int fd_has_wildcards(char *s) { if (!s) return(0); while (*s) { if (*s == '*' || *s == '?') return(1); s++; } return(0); } static void fd_split_pattern(char *spec, char *dir, char *pat) { char tmp[260]; char *p; if (!spec || !*spec) { strcpy(dir, "."); strcpy(pat, "*.*"); return; } strmaxcpy(tmp, spec, sizeof(tmp) - 1); p = strrchr(tmp, '\\'); if (!p) p = strrchr(tmp, '/'); if (p) { *p++ = '\0'; if (tmp[0]) strmaxcpy(dir, tmp, 259); else strcpy(dir, "."); strmaxcpy(pat, p, 259); } else { strcpy(dir, "."); strmaxcpy(pat, tmp, 259); } if (!pat[0]) strcpy(pat, "*.*"); } static void fd_join_path(char *out, char *dir, char *name, int max) { int len; out[0] = '\0'; if (!dir || !dir[0] || fd_same(dir, ".")) { strmaxcpy(out, name, max - 1); return; } strmaxcpy(out, dir, max - 1); len = strlen(out); if (len > 0 && out[len - 1] != '\\' && out[len - 1] != '/' && out[len - 1] != ':') { if (len < max - 1) { out[len++] = '\\'; out[len] = '\0'; } } if ((int)(strlen(out) + strlen(name)) < max - 1) strcat(out, name); } static void fd_basename(char *out, char *path, int max) { char up[260]; char *p; fd_upcopy(up, path, sizeof(up)); p = strrchr(up, '\\'); if (!p) p = strrchr(up, ':'); if (p) strmaxcpy(out, p + 1, max - 1); else strmaxcpy(out, up, max - 1); } static void fd_help(void) { fprintf(stdout, "386 Usage: Flagdir [path [option...]]\n"); fprintf(stdout, "Options: Normal\n"); fprintf(stdout, " System\n"); fprintf(stdout, " Hidden\n"); fprintf(stdout, " Deleteinhibit\n"); fprintf(stdout, " Purge\n"); fprintf(stdout, " Renameinhibit\n"); } static int fd_attr_mask(char *s, uint32 *setbits, uint32 *clearbits) { if (fd_same(s, "N") || fd_same(s, "NORMAL")) { *clearbits |= FD_DIR_BITS; } else if (fd_same(s, "S") || fd_same(s, "SY") || fd_same(s, "SYS") || fd_same(s, "SYSTEM")) { *setbits |= FD_NWFA_SY; } else if (fd_same(s, "H") || fd_same(s, "HIDDEN")) { *setbits |= FD_NWFA_H; } else if (fd_same(s, "DI") || fd_same(s, "DELETEINHIBIT")) { *setbits |= FD_NWFA_DI; } else if (fd_same(s, "P") || fd_same(s, "PURGE")) { *setbits |= FD_NWFA_P; } else if (fd_same(s, "RI") || fd_same(s, "RENAMEINHIBIT")) { *setbits |= FD_NWFA_RI; } else if (fd_same(s, "PRIVATE") || fd_same(s, "PR")) { fprintf(stderr, "Private is valid on NetWare 2.15 and above, except NetWare 386.\n"); return(-1); } else { fprintf(stderr, "Unknown attribute: %s.\n", s); return(-1); } return(0); } static void fd_print_attrs(uint32 attrs) { int any = 0; if (!(attrs & FD_DIR_BITS)) { fprintf(stdout, "Normal\n"); return; } if (attrs & FD_NWFA_SY) { fprintf(stdout, "System"); any = 1; } if (attrs & FD_NWFA_H) { fprintf(stdout, "%sHidden", any ? " " : ""); any = 1; } if (attrs & FD_NWFA_DI) { fprintf(stdout, "%sDeleteInhibit", any ? " " : ""); any = 1; } if (attrs & FD_NWFA_P) { fprintf(stdout, "%sPurge", any ? " " : ""); any = 1; } if (attrs & FD_NWFA_RI) { fprintf(stdout, "%sRenameInhibit", any ? " " : ""); any = 1; } fprintf(stdout, "\n"); } static void fd_display_header(char *path) { char up[260]; char prefix[90]; fd_upcopy(up, path, sizeof(up)); if (fd_current_prefix(prefix, sizeof(prefix))) prefix[0] = '\0'; fprintf(stdout, "%s%s \n", prefix, up); } static void fd_display_row(char *name, uint32 attrs) { char base[260]; fd_basename(base, name, sizeof(base)); fprintf(stdout, " %-12.12s ", base); fd_print_attrs(attrs); } static void fd_display(char *path, uint32 attrs) { fd_display_header(path); fd_display_row(path, attrs); } static int fd_is_directory(char *path) { struct find_t ff; unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH; if (fd_is_current_path(path)) return(1); if (_dos_findfirst(path, attr, &ff)) return(0); return((ff.attrib & _A_SUBDIR) != 0); } static int fd_obtain(char *path, uint8 dhandle, uint32 *attrs) { if (c32_ncp87_obtain_rim_attributes(path, (uint16)dhandle, attrs, NULL, NULL, NULL) == 0) return(0); return(-1); } static int fd_modify(char *path, uint8 dhandle, uint32 attrs) { if (c32_ncp87_modify_dos_attributes(path, (uint16)dhandle, attrs, NULL, NULL, NULL) == 0) return(0); return(-1); } static int fd_process_one(char *path, char *display_path, uint8 dhandle, uint32 setbits, uint32 clearbits, int have_change, int show_header) { char *ncp_path; uint32 attrs; uint32 newattrs; if (!fd_is_directory(path)) { fprintf(stderr, "Directory %s not found.\n", path); return(1); } ncp_path = fd_is_current_path(path) ? "" : path; if (fd_obtain(ncp_path, dhandle, &attrs)) { if (fd_is_current_path(path) && display_path && !display_path[0] && !have_change) { attrs = 0; } else { fprintf(stderr, "Unable to get directory attributes.\n"); return(1); } } if (have_change) { newattrs = (attrs | setbits) & ~clearbits; if (newattrs != attrs) { if (fd_modify(ncp_path, dhandle, newattrs)) { fprintf(stderr, "Unable to change attributes.\n"); return(1); } attrs = newattrs; fd_obtain(ncp_path, dhandle, &attrs); } } if (show_header) fd_display(display_path, attrs); else fd_display_row(display_path, attrs); return(0); } static int fd_process_wild(char *spec, uint8 dhandle, uint32 setbits, uint32 clearbits, int have_change) { struct find_t ff; char dir[260]; char pat[260]; char search[260]; char full[260]; int found = 0; int rc = 0; int lines = 0; int continuous = 0; unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH; fd_split_pattern(spec, dir, pat); fd_join_path(search, dir, pat, sizeof(search)); if (_dos_findfirst(search, attr, &ff) != 0) { fprintf(stderr, "Directory %s not found.\n", spec); return(1); } fd_display_header(spec); do { if ((ff.attrib & _A_SUBDIR) && strcmp(ff.name, ".") && strcmp(ff.name, "..")) { fd_join_path(full, dir, ff.name, sizeof(full)); if (fd_process_one(full, ff.name, dhandle, setbits, clearbits, have_change, 0)) rc = 1; found++; tool_page_line(&lines, &continuous); } } while (_dos_findnext(&ff) == 0); if (!found) { fprintf(stderr, "Directory %s not found.\n", spec); return(1); } return(rc); } int func_flagdir(int argc, char *argv[], int mode) { char *path = "."; char display_path[260]; uint8 dhandle = 0; uint32 setbits = 0; uint32 clearbits = 0; int have_change = 0; int i; (void)mode; if (argc > 1 && (fd_same(argv[1], "/?") || fd_same(argv[1], "-?") || fd_same(argv[1], "?"))) { fd_help(); return(0); } if (argc > 1) path = argv[1]; if (fd_current_dhandle(&dhandle)) { fprintf(stderr, "FlagDir only works on network directories.\n"); return(1); } for (i = 2; i < argc; i++) { if (fd_attr_mask(argv[i], &setbits, &clearbits)) return(1); have_change = 1; } if (fd_has_wildcards(path)) return(fd_process_wild(path, dhandle, setbits, clearbits, have_change)); if (fd_is_current_path(path)) { if (fd_current_display_path(dhandle, display_path, sizeof(display_path))) strcpy(display_path, "."); } else { strmaxcpy(display_path, path, sizeof(display_path) - 1); } return(fd_process_one(path, display_path, dhandle, setbits, clearbits, have_change, 1)); }