Logo Search packages:      
Sourcecode: ncpfs version File versions  Download package

nwdir.c

/*
    nwdir.c - list contents of directory
    Copyright (c) 1998       Milan Vandrovec
    Copyright (c) 1999-2001  Petr Vandrovec
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


    Revision history:

      0.00  1998              Milan Vandrovec
            Initial revision.

      0.01  1999              Petr Vandrovec <vandrove@vc.cvut.cz>
            Updated for new ncp_ns_* interface.

      1.00  1999, November 20       Petr Vandrovec <vandrove@vc.cvut.cz>
            Added license.
  
      1.01  2000, August 24         Petr Vandrovec <vandrove@vc.cvut.cz>
            Updated to ncp_ns_search_init/ncp_ns_search_next/
                  ncp_ns_search_end.
            Updated to ncp_ns_extract_info_field.

      1.02  2000, August 27         Petr Vandrovec <vandrove@vc.cvut.cz>
            Added ncp_ea_enumerate code.
            
      1.03  2001, January 27        Petr Vandrovec <vandrove@vc.cvut.cz>
            Updated to use getopt interface.
            Added ncp_ns_scan_connections_using_file dump code.

      1.04  2001, February 4        Petr Vandrovec <vandrove@vc.cvut.cz>
            Added ncp_ns_scan_physical_locks_by_file dump code.

      1.05  2001, May 31            Petr Vandrovec <vandrove@vc.cvut.cz>
            Use unistd.h and not getopt.h for getopt().

      1.06  2002, February 4        Petr Vandrovec <vandrove@vc.cvut.cz>
            Do not dump core when file opened for nothing is found.

 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#include <ncp/nwcalls.h>
#include <ncp/nwnet.h>
#include <ncp/eas.h>

#include "private/libintl.h"
#define _(X) gettext(X)
#define N_(X) (X)

#ifndef A_DONT_SUBALLOCATE
#define A_DONT_SUBALLOCATE  0x00000800L
#endif

#ifdef N_PLAT_DOS
#ifndef NTYPES_H
typedef unsigned int   nuint16;
#endif
typedef unsigned long  nuint32;
typedef unsigned int   nuint;
#define P08X      "(%08lX)"
#define P32U      "lu"
#else
#define stricmp(A,B) strcasecmp(A,B)
#define P08X      "(%08X)"
#define P32U      "u"
#endif

static int opt_t = 0;
static int opt_l = 0;
static int opt_v = 0;
static int opt_e = 0;
static int opt_f = 0;
static int opt_p = 0;

static void ncpb_add_byte(unsigned char** c, int v) {
  *(*c)++ = v;
}

static void ncpb_add_word_lh(unsigned char** c, nuint v) {
  WSET_LH(*c, 0, v);
  (*c)+=2;
}

static void ncpb_add_dword_lh(unsigned char** c, nuint32 v) {
  DSET_LH(*c, 0, v);
  (*c)+=4;
}

static nuint16 ncpb_get_word_lh(unsigned char** c) {
  nuint16 tmp;
  tmp = WVAL_LH(*c, 0);
  (*c)+=2;
  return tmp;
}

u_int32_t img;
struct nsInfo {
      struct NSI_Name        name;
      struct NSI_Directory dir;
      int                  valid;
};

static struct nsInfo os2, mac, nfs;

static unsigned char buf[1024];
static unsigned char buf2[1024];

static NWCCODE NWNSEntryInfo2(NWCONN_HANDLE conn, nuint32 vol, nuint32 dosdir, nuint ns, struct NSI_Name* name, struct NSI_Directory* dir) {
      struct nw_info_struct3 info;
      NWCCODE err;

      info.len = 0;
      info.data = NULL;

      err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL,
            1, vol, dosdir, NULL, 0, ns, RIM_NAME | RIM_DIRECTORY,
            &info, sizeof(info));
      if (err)
            return err;
      err = ncp_ns_extract_info_field(&info, NSIF_NAME, name, sizeof(*name));
      if (!err) {
            err = ncp_ns_extract_info_field(&info, NSIF_DIRECTORY, dir, sizeof(*dir));
      }
      free(info.data);
      return err;
}

static NWCCODE NWNSScanForTrustees(NWCONN_HANDLE conn, 
            nuint32 vol, nuint32 dosdir, 
            nuint32* iter, nuint* no_tstees, TRUSTEE_INFO* tstees) {
      return ncp_ns_trustee_scan(conn, NW_NS_DOS, SA_ALL, 
            1, vol, dosdir, NULL, 0, iter, tstees, no_tstees);
}

static NWCCODE NWNSGetEffectiveRights(NWCONN_HANDLE conn, nuint32 vol, nuint32 dosdir, nuint16* eff) {
      unsigned char* c=buf2;
      NW_FRAGMENT rq;
      NW_FRAGMENT rp;
      NWCCODE err;

      ncpb_add_byte(&c, 0x1D);
      ncpb_add_byte(&c, NW_NS_DOS);
      ncpb_add_byte(&c, 0);         /* ?? */
      ncpb_add_word_lh(&c, SA_ALL);
      ncpb_add_dword_lh(&c, 0);     /* ReturnInfoMask=0, we are not interested in anything */
      ncpb_add_byte(&c, vol);
      ncpb_add_dword_lh(&c, dosdir);
      ncpb_add_byte(&c, 1);
      ncpb_add_byte(&c, 0);
      rq.fragAddress = buf2;
      rq.fragSize = c-buf2;
      rp.fragAddress = buf;
      rp.fragSize = sizeof(buf);
      err = NWRequest(conn, 0x57, 1, &rq, 1, &rp);
      if (err) return err;
      c = buf;
      *eff = ncpb_get_word_lh(&c);
      return 0;
}

static char* createMask311(nuint mask) {
      static char r[9];

      r[0] = (mask&TR_SUPERVISOR) ?'S':'-';
      r[1] = (mask&TR_READ)       ?'R':'-',
      r[2] = (mask&TR_WRITE)      ?'W':'-',
      r[3] = (mask&TR_CREATE)     ?'C':'-',
      r[4] = (mask&TR_ERASE)      ?'E':'-',
      r[5] = (mask&TR_MODIFY)     ?'M':'-',
      r[6] = (mask&TR_SEARCH)     ?'F':'-',
      r[7] = (mask&TR_ACCESS_CTRL)?'A':'-',
      r[8] = 0;
      return r;
}

static void doID(NWCONN_HANDLE conn, nuint32 id) {
      NWCCODE err;
      char user[MAX_DN_BYTES];
      nuint16 type;

      if (opt_t)
            printf(P08X " ", id);
      if (!id) {
            printf(_("Nobody"));
      } else {
#ifdef N_PLAT_DOS
            id = ntohl(id);
#endif
            err = NWGetObjectName(conn, id, user, &type);
            if (err) {
                  NWDSContextHandle ctx;
                  
                  sprintf(user, _("Unknown:N/A"));
                  err = NWDSCreateContextHandle(&ctx);
                  if (!err) {
                        NWDSAddConnection(ctx, conn);
                        err = NWDSMapIDToName(ctx, conn, id, user);
                        if (err)
                              sprintf(user, _("Unknown:<%s>"), strnwerror(err));
                        NWDSFreeContext(ctx);
                  }
            } else {
                  switch (type) {
                        case OT_USER:       printf(_("User:"));break;
                        case OT_USER_GROUP: printf(_("Group:"));break;
                        case OT_FILE_SERVER:printf(_("FileServer:"));break;
                        default:            printf(_("Unknown(%04X):"), type);break;
                  }
            }
            printf("%s", user);
      }
}

static inline size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
      return strftime(s, max, fmt, tm);
}

static void dodate(nuint date) {
      static const time_t zero_time_t = 0;
      struct tm* tm;
      char text[100];
      
      tm = gmtime(&zero_time_t);
      tm->tm_year = (date>>9)+80;
      tm->tm_mon = ((date>>5) & 0xF) - 1;
      tm->tm_mday = date & 0x1F;
      tm->tm_isdst = 0;
      my_strftime(text, sizeof(text), "%x", tm);
      printf("%s", text);
}

static void dotime(nuint dtime) {
      static const time_t zero_time_t = 0;
      struct tm* tm;
      char text[100];
      
      tm = gmtime(&zero_time_t);
      tm->tm_hour = dtime >> 11;
      tm->tm_min = (dtime >> 5) & 0x3F;
      tm->tm_sec = (dtime << 1) & 0x3F;
      tm->tm_isdst = 0;
      my_strftime(text, sizeof(text), "%X", tm);
      printf("%s", text);
}

static void dodatesTimesID(NWCONN_HANDLE conn, nuint dtime, nuint date, nuint32 id) {
      if (dtime || date) {
            dodate(date);
            printf(" ");
            dotime(dtime);
      } else {
            printf("%-17s", _("never"));
      }
      if (id) {
            printf(" ");
            doID(conn, id);
      }
      printf("\n");
}

static void eaenum(NWCONN_HANDLE conn, u_int32_t volume, u_int32_t dirent) {
      unsigned char vv[2048];
      size_t pos;
      struct ncp_ea_enumerate_info winfo;
      NWCCODE err;
      int sawtitle = 0;
      size_t eaid = 1;

      winfo.enumSequence = 0;
      err = ncp_ea_enumerate(conn,
            NWEA_FL_INFO1 | NWEA_FL_CLOSE_ERR | NWEA_FL_SRC_DIRENT,
            volume, dirent, -1, NULL, 0, &winfo, vv, sizeof(vv), &pos);
      do {
            size_t rinfo;
            const unsigned char* p;

            if (err) {
                  //fprintf(stderr, "Enumeration failed: %s\n", 
                  //    strnwerror(err));
                  return;
            }
            if (winfo.errorCode) {
                  /* should not happen as we used NWEA_FL_CLOSE_ERR */
                  //fprintf(stderr, "Enumeration extended fail: %s\n", 
                  //    strnwerror((winfo.errorCode & 0xFF) | NWE_SERVER_ERROR));
                  break;
            }
            /* no extended attributes */
            if (!winfo.totalEAs)
                  break;
            if (!sawtitle) {
                  printf(_("Extended attributes: %u attributes\n"
                           "                     %u bytes in keys, %u bytes in data\n"), 
                              winfo.totalEAs, winfo.totalEAsKeySize, winfo.totalEAsDataSize);
                  sawtitle = 1;
            }

            p = vv;
            for (rinfo = 0; rinfo < winfo.returnedItems; rinfo++) {
                  struct ncp_ea_info_level1 ppp;

                  err = ncp_ea_extract_info_level1(p,
                        vv + pos, &ppp, sizeof(ppp), NULL, &p);
                  if (err)
                        printf("  Key %u: Cannot retrieve: %s\n",
                              eaid, strnwerror(err));
                  else {
                        printf(_("  Key %u:\n"
                                 "    Name:         %s\n"
                               "    Access Flag:  0x%08X\n"
                               "    Value Length: %u\n"), 
                               eaid, ppp.key, ppp.accessFlag, 
                               ppp.valueLength);
                  }
                  eaid++;
            }
            if (!winfo.enumSequence)
                  break;
            err = ncp_ea_enumerate(conn, 
                  NWEA_FL_INFO1 | NWEA_FL_CLOSE_ERR | NWEA_FL_SRC_EAHANDLE,
                  winfo.newEAhandle, 0, -1, NULL, 0,
                  &winfo, vv, sizeof(vv), &pos);
      } while (1);
      if (winfo.newEAhandle) {
            err = ncp_ea_close(conn, winfo.newEAhandle);
//          if (err) {
//                fprintf(stderr, "Close EA failed: %s\n",
//                      strnwerror(err));
//          }
      }
      if (sawtitle)
            printf("\n");
}

static void dumpDataSizes(const struct nw_info_struct3* info) {
      NWCCODE err;
      struct NSI_DatastreamLogicals* logical;
      size_t tmplen;
      
      if (!(img & RIM_DATASTREAM_LOGICALS)) {
            ncp_off64_t off;

            err = ncp_ns_extract_info_field(info, NSIF_DATA_SIZE,
                  &off, sizeof(off));
            if (err) {
                  printf(_("  Cannot determine file size: %s\n"), strnwerror(err));
            } else {
                  printf(_("  File size:       %10Lu"), off);

                  err = ncp_ns_extract_info_field(info, NSIF_SPACE_ALLOCATED,
                        &off, sizeof(off));
                  if (!err) {
                        printf(_(" (allocated %Lu)"), off * 8ULL);
                  }
                  printf("\n");
            }
            return;
      }
      err = ncp_ns_extract_info_field_size(info, NSIF_DATASTREAM_LOGICALS,
            &tmplen);
      if (err)
            return;
      logical = (struct NSI_DatastreamLogicals*)malloc(tmplen);
      if (!logical)
            return;
      err = ncp_ns_extract_info_field(info, NSIF_DATASTREAM_LOGICALS,
            logical, tmplen);
      if (err) {
            printf(_("  Cannot determine file size: %s\n"), strnwerror(err));
      } else if (!logical->NumberOfDatastreams) {
            printf(_("  No datastream exist\n"));
      } else {
            struct NSI_DatastreamSizes* size;
            size_t i;
            
            size = NULL;
            err = ncp_ns_extract_info_field_size(info, NSIF_DATASTREAM_SIZES,
                  &tmplen);
            if (!err) {
                  size = (struct NSI_DatastreamSizes*)malloc(tmplen);
                  if (size) {
                        err = ncp_ns_extract_info_field(info,
                              NSIF_DATASTREAM_SIZES, size, tmplen);
                        if (err) {
                              free(size);
                              size = NULL;
                        }
                  }
            }
            for (i = 0; i < logical->NumberOfDatastreams; i++) {
                  size_t j;
                  u_int32_t num = logical->ds[i].Number;
                  
                  if (num) {
                        printf(_("  Stream %3u size: %10Lu"), num,
                              logical->ds[i].Size);
                  } else {
                        printf(_("  File size:       %10Lu"),
                              logical->ds[i].Size);
                  }
                  if (size) {
                        for (j = 0; j < size->NumberOfDatastreams; j++) {
                              if (size->ds[j].Number == num) {
                                    printf(_(" (allocated %Lu)"),
                                          ((ncp_off64_t)size->ds[j].FATBlockSize) * 512ULL);
                                    break;                              
                              }
                        }
                  }
                  printf("\n");
            }
            if (size)
                  free(size);
      }
      free(logical);
}

static void dumpit(NWCONN_HANDLE conn, const struct nw_info_struct3* info) {
      NWCCODE err;
      struct NSI_Attributes attr;
      struct NSI_Name name;
      struct NSI_Directory dir;
      
      err = ncp_ns_extract_info_field(info, NSIF_ATTRIBUTES, &attr, sizeof(attr));
      if (err) {
            fprintf(stderr, _("Cannot retrieve file attributes: %s\n"),
                  strnwerror(err));
            return;
      }
      err = ncp_ns_extract_info_field(info, NSIF_DIRECTORY, &dir, sizeof(dir));
      if (err) {
            fprintf(stderr, _("Cannot retrieve file number: %s\n"),
                  strnwerror(err));
            return;
      }
      err = ncp_ns_extract_info_field(info, NSIF_NAME, &name, sizeof(name));
      if (err) {
            fprintf(stderr, _("Cannot retrieve file name: %s\n"),
                  strnwerror(err));
            return;
      }
      if (attr.Attributes & A_DIRECTORY) {
            printf(_("Directory:\n"));
      } else {
            printf(_("File:\n"));
      }
      if (opt_v || opt_l) {
            err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_OS2, &os2.name, &os2.dir);
            os2.valid = err==0;
            err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_MAC, &mac.name, &mac.dir);
            mac.valid = err==0;
            err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_NFS, &nfs.name, &nfs.dir);
            nfs.valid = err==0;
      } else {
            os2.valid = 0;
            mac.valid = 0;
            nfs.valid = 0;
      }
      printf(_("  DOS:  "));
      if (opt_t) 
            printf(P08X " ", dir.dirEntNum);
      printf("%s\n", name.Name);
      if (os2.valid) {
            printf(_(" OS/2:  "));
            if (opt_t)
                  printf(P08X " ", os2.dir.dirEntNum);
            printf("%s\n", os2.name.Name);
      }
      if (nfs.valid) {
            printf(_("  NFS:  "));
            if (opt_t)
                  printf(P08X " ", nfs.dir.dirEntNum);
            printf("%s\n", nfs.name.Name);
      }
      if (mac.valid) {
            printf(_("  MAC:  "));
            if (opt_t)
                  printf(P08X " ", mac.dir.dirEntNum);
            printf("%s\n", mac.name.Name);
      }
      printf("\n");
      if (opt_v) {
            u_int32_t inheritedRightsMask;
            
            printf(_("Rights:\n"));
            printf(_("  Inherited: "));
            err = ncp_ns_extract_info_field(info, NSIF_RIGHTS,
                  &inheritedRightsMask, sizeof(inheritedRightsMask));
            if (err) {
                  printf(_("Cannot determine: %s\n"), strnwerror(err));
            } else {
                  nuint32 eff32;
                  
                  if (opt_t)
                        printf("(%04X) ", inheritedRightsMask);
                  printf("[%s]\n", createMask311(inheritedRightsMask));
                  
                  err = ncp_ns_extract_info_field(info, NSIF_EFFECTIVE_RIGHTS,
                        &eff32, sizeof(eff32));
                  if (err) {
                        nuint16 eff;

                        err = NWNSGetEffectiveRights(conn, 
                              dir.volNumber, dir.DosDirNum, &eff);
                        eff32 = eff;
                  }
                  printf(_("  Effective: "));
                  if (err) {
                        printf(_("Cannot determine: %s\n"), strnwerror(err));
                  } else {
                        if (opt_t)
                              printf("(%04X) ", eff32);
                        printf("[%s]\n", createMask311(eff32));
                  }
            }
            printf("\n");
      }
      if (opt_l || opt_v) {
            u_int32_t ns;
            
            printf(_("Owning namespace: "));
            err = ncp_ns_extract_info_field(info, NSIF_OWNING_NAMESPACE,
                  &ns, sizeof(ns));
            if (err) {
                  printf(_("Cannot determine: %s\n"), strnwerror(err));
            } else {
                  if (opt_t)
                        printf("(%" P32U ") ", ns);
                  printf("%s\n", ncp_namespace_to_str(NULL, ns));
            }
            printf("\n");
      }
      if (opt_v) {
            struct NSI_Modify modify;
            struct NSI_Change change;
            NWCCODE moderr;
            
            printf(_("Miscellaneous NetWare Information:\n"));
            printf(_("  Last update:    "));
            moderr = ncp_ns_extract_info_field(info, NSIF_MODIFY,
                  &modify, sizeof(modify));
            if (moderr) {
                  printf(_("Cannot determine: %s\n"), strnwerror(moderr));
            } else {
                  dodatesTimesID(conn, modify.Modify.Time, modify.Modify.Date, modify.Modify.ID);
            }
            printf(_("  Last archived:  "));
            err = ncp_ns_extract_info_field(info, NSIF_ARCHIVE,
                  &change, sizeof(change));
            if (err) {
                  printf(_("Cannot determine: %s\n"), strnwerror(err));
            } else {
                  dodatesTimesID(conn, change.Time, change.Date, change.ID);
            }
            if (1 || !(attr.Attributes&A_DIRECTORY)) {
                  printf(_("  Last accessed:  "));
                  if (moderr) {
                        printf(_("Cannot determine: %s\n"), strnwerror(moderr));
                  } else {
                        dodatesTimesID(conn, modify.LastAccess.Time, modify.LastAccess.Date, 0);
                  }
            }
            printf(_("  Created/Copied: "));
            err = ncp_ns_extract_info_field(info, NSIF_CREATION,
                  &change, sizeof(change));
            if (err) {
                  printf(_("Cannot determine: %s\n"), strnwerror(err));
            } else {
                  dodatesTimesID(conn, change.Time, change.Date, change.ID);
            }
            printf(_("  Flags:          [%s%s%s%s]"),
                  (attr.Attributes&A_READ_ONLY     )?"Ro":"Rw",
                  (attr.Attributes&A_SYSTEM        )?"Sy":"--",
                  (attr.Attributes&A_HIDDEN        )?"H" :"-",
                  (attr.Attributes&A_NEEDS_ARCHIVED)?"A" :"-");
            printf(" [%s%s%s%s" "%s%s%s" "%s" "%s%s%s%s%s]",
                  (attr.Attributes&A_EXECUTE_ONLY  )?"X" :"-",
                  (attr.Attributes&A_TRANSACTIONAL )?"T" :"-",
                  (attr.Attributes&A_IMMEDIATE_PURGE)?"P":"-",
                  (attr.Attributes&A_SHAREABLE     )?"Sh":"--",

                  (attr.Attributes&A_DELETE_INHIBIT)?"Di":"--",
                  (attr.Attributes&A_COPY_INHIBIT  )?"Ci":"--",
                  (attr.Attributes&A_RENAME_INHIBIT)?"Ri":"--",

                  (attr.Attributes&A_DONT_COMPRESS )?"Dc":
                        (attr.Attributes&A_IMMEDIATE_COMPRESS)?"Ic":"--",

                  (attr.Attributes&A_DONT_MIGRATE  )?"Dm":"--",
                  (attr.Attributes&A_DONT_SUBALLOCATE)?"Ds":"--",
                  (attr.Attributes&A_INDEXED       )?"I":"--",
                  (attr.Attributes&A_READ_AUDIT    )?"Ra":"--",
                  (attr.Attributes&A_WRITE_AUDIT   )?"Wa":"--");
            printf(" [%s%s]",
                  (attr.Attributes&A_FILE_COMPRESSED)?"Co":
                        (attr.Attributes&A_CANT_COMPRESS)?"Cc":"--",
                  (attr.Attributes&A_FILE_MIGRATED )?"M":"-");
            if (opt_t)
                  printf(" " P08X, attr.Attributes);
            printf("\n");
            if (!(attr.Attributes&A_DIRECTORY)) {
                  dumpDataSizes(info);
            }
            printf("\n");
            {
                  nuint32 iter = 0;
                  int first = 1;

                  while (1) {
                        nuint tcount;
                        nuint i;
                        TRUSTEE_INFO tstees[40];

                        tcount = 40;
                        err = NWNSScanForTrustees(conn, dir.volNumber, 
                              dir.DosDirNum, &iter, &tcount, tstees);
                          if (err)
                              break;
                        for (i=0; i<tcount; i++) {
                              if (first) {
                                    printf(_("Trustees:\n"));
                                    first = 0;
                              }
                              printf("  [%s] ", createMask311(tstees[i].objectRights));
                              doID(conn, tstees[i].objectID);
                              printf("\n");
                        }
                  }
                  if (!first)
                        printf("\n");
            } 
      }
      if (opt_e)
            eaenum(conn, dir.volNumber, dir.DosDirNum);
      if (opt_f) {
            u_int16_t iterHandle = 0;
            CONN_USING_FILE cf;
            CONNS_USING_FILE cfa;
            int first = 1;

            while (ncp_ns_scan_connections_using_file(conn, dir.volNumber, dir.DosDirNum, 0, &iterHandle, &cf, &cfa) == 0) {
                  if (cfa.connCount != 0) {
                        time_t t;
                        struct ncp_bindery_object o;
                        
                        if (first) {
                                printf(_("File Usage:\n"));
                              printf(_("  Use Count:              %5u  Open Count:              %5u\n"
                                       "  Open For Reading Count: %5u  Open For Writting Count: %5u\n"
                                     "  Deny Read Count:        %5u  Deny Write Count:        %5u\n"
                                     "  Locked:       %-15s  Fork Count:              %5u\n"),
                                     cfa.useCount, cfa.openCount, cfa.openForReadCount, cfa.openForWriteCount,
                                     cfa.denyReadCount, cfa.denyWriteCount, cfa.locked ? "exclusive" : "no",
                                     cfa.forkCount);
                              printf(_("  Connection Count:  %10u\n"), cfa.connCount);
                              first = 0;
                        }
                        
                        printf(_("    Connection: %u/%u"), cf.connNumber, cf.taskNumber);
                        err = ncp_get_stations_logged_info(conn, cf.connNumber, &o, &t);
                        if (!err) {
                              printf(_(", "));
                              doID(conn, o.object_id);
                        }
                        printf("\n");
                        {
                              static const char* lock_bits[] = {N_("locked"), N_("open shareable"),
                                                               N_("logged"), N_("open normal"),
                                                       N_("rsvd"), N_("rsvd"),
                                                       N_("TTS locked"), N_("TTS")};
                              static const char* acc_bits[] = {N_("read"), N_("write"),
                                                       N_("deny read"), N_("deny write"),
                                                       N_("detached"), N_("TTS holding detach"),
                                                       N_("TTS holding open"), N_("rsvd")};
                              char lstr[200];
                              char accstr[200];
                              char* l2str;
                              char* p;
                              int i;
                              
                              p = NULL;
                              for (i = 0; i < 8; i++) {
                                    if (cf.lockType & (1 << i)) {
                                          if (p) {
                                                strcpy(p, ", ");
                                                p = strchr(p, 0);
                                          } else {
                                                p = lstr;
                                          }
                                          strcpy(p, _(lock_bits[i]));
                                          p = strchr(p, 0);
                                    }
                              }
                              if (!p) {
                                    strcpy(lstr, _("unlocked"));
                              }
                              switch (cf.lockFlag) {
                                    case 0x00:  l2str = _("Not locked"); break;
                                    case 0xFE:  l2str = _("Locked by a file lock"); break;
                                    case 0xFF:  l2str = _("Locked by Begin Share File Set"); break;
                                    default:    l2str = _("Unknown lock state"); break;
                              }
                              p = NULL;
                              for (i = 0; i < 8; i++) {
                                    if (cf.accessControl & (1 << i)) {
                                          if (p) {
                                                strcpy(p, ", ");
                                                p = strchr(p, 0);
                                          } else {
                                                p = accstr;
                                          }
                                          strcpy(p, _(acc_bits[i]));
                                          p = strchr(p, 0);
                                    }
                              }
                              if (!p) {
                                    strcpy(accstr, _("unlocked"));
                              }
                              if (opt_t) {
                                    printf(_("          Lock:   (%02X) %s\n"), cf.lockType, lstr);
                                    printf(_("                  (%02X) %s\n"), cf.lockFlag, l2str);
                                    printf(_("          Access: (%02X) %s\n"), cf.accessControl, accstr);
                              } else {
                                    printf(_("          Lock:   %s\n"), lstr);
                                    printf(_("                  %s\n"), l2str);
                                    printf(_("          Access: %s\n"), accstr);
                              }
                        }
                  }
            }
            if (!first) {
                  printf("\n");
            }
      }
      if (opt_p) {
            u_int16_t iterHandle = 0;
            PHYSICAL_LOCK pl;
            PHYSICAL_LOCKS pls;
            int first = 1;

            while (ncp_ns_scan_physical_locks_by_file(conn, dir.volNumber, dir.DosDirNum, 0, &iterHandle, &pl, &pls) == 0) {
                  if (pls.numRecords != 0) {
                        time_t t;
                        struct ncp_bindery_object o;
                        
                        if (first) {
                                printf(_("File Physical Locks:\n"));
                              first = 0;
                        }
                        
                        printf(_("    Connection: %u/%u"), pl.connNumber, pl.taskNumber);
                        err = ncp_get_stations_logged_info(conn, pl.connNumber, &o, &t);
                        if (!err) {
                              printf(_(", "));
                              doID(conn, o.object_id);
                        }
                        printf("\n");
                        printf(_("    Range: 0x%08LX-0x%08LX\n"), pl.recordStart, pl.recordEnd);
                  }
            }
            if (!first) {
                  printf("\n");
            }
      }
}

static void listdir(NWCONN_HANDLE conn, nuint32 volume, nuint32 dirent, char* mask) {
      NWDIRLIST_HANDLE h;
      NWCCODE err;
      size_t maskl = strlen(mask);

      err = ncp_ns_search_init(conn, NW_NS_DOS, SA_ALL, 1,
            volume, dirent, NULL, 0,
            0, mask, maskl, img, &h);
      if (err) {
            fprintf(stderr, _("Unable to begin scandir: 0x%04X\n"), err);
            return;
      }
      while (1) {
            struct nw_info_struct3 info;
            
            info.len = 0;
            info.data = NULL;
            err = ncp_ns_search_next(h, &info, sizeof(info));
            if (err) {
                  if (err != NWE_SERVER_FAILURE) {
                        /* Non-standard error code */
                        fprintf(stderr, _("Unexpected error in NextDir: %s\n"), strnwerror(err));
                  }
                  break;
            }
            dumpit(conn, &info);
            if (info.data)
                  free(info.data);
      }
      ncp_ns_search_end(h);
}

static char volname[17];
static char dirpath[512];
static char fullpath[600];

static struct nw_info_struct2 dosNS2;

static void usage(void) {
  fprintf(stderr, _("nwdir [options] [path]\n"
              "\n"
              "      -d    List information about directory itself instead\n"
              "            of directory content\n"
                  "      -l    List namespace informations\n"
              "      -e    List extended attributes informations\n"
              "      -v    Verbose listing\n"
              "      -f    List connections using file\n"
              "      -p    List physical locks on file\n"
              "      -t    Technical - show values and their meaning\n"
              "      -h    This help\n"
              "      path  Path to list, may contain wildcards\n"
              "\n"
              "(c) 1998 Milan Vandrovec for ncpfs-2.0.12.8\n"));
}

static char dwild[200];

static void makewild(char* wildout, const char* wildin) {
  unsigned char c;

  while ((c=*wildin++)!=0) {
    switch (c) {
#ifdef N_PLAT_DOS
      case '.':
#endif
      case '*':
      case '?':*wildout++ = '\377';
#ifdef N_PLAT_DOS
             *wildout++ = c | 0x80;
#else
             *wildout++ = c;
#endif
             break;
     case 0xFF:*wildout++ = 0xFF;
       default:*wildout++ =c;
             break;
    }
  }
  *wildout=0;
}

int main(int argc, char* argv[]) {
      NWCCODE err;
      NWCONN_HANDLE conn;
      char* path;
      char* xpath;
      char* lst;
      const char* dpath;
      int wild;
      int opt_d = 0;
      int i;
      u_int16_t nwver;

      setlocale(LC_ALL, "");
      bindtextdomain(NCPFS_PACKAGE, LOCALEDIR);
      textdomain(NCPFS_PACKAGE);
      
      while ((i = getopt(argc, argv, "dltvefph")) != -1) {
            switch (i) {
                  case 'd':   opt_d = 1; break;
                  case 'l':   opt_l = 1; break;
                  case 't':   opt_t = 1; break;
                  case 'v':   opt_v = 1; break;
                  case 'e':   opt_e = 1; break;
                  case 'f':   opt_f = 1; break;
                  case 'p':   opt_p = 1; break;
                  case 'h':   usage(); return 123;
            }
      }
      i = optind;
      if (i < argc) {
            path = argv[i++];
      } else {
            path = (char*)".";
      }
      err = NWCallsInit(NULL, NULL);
      if (err) {
            fprintf(stderr, _("Unable to initialize: 0x%04X\n"), err);
            return 123;
      }
      xpath = path;
      lst = xpath;
      wild = 0;
      for (path=xpath; *path; path++) {
            switch (*path) {
#ifdef N_PLAT_DOS
                  case '\\':
#endif
                  case '/': lst=path; wild=0; break;
                  case '?':
                  case '*': wild=1; break;
                  default:  break;
            }
      }
      if (wild) {
            if (lst == xpath) {
                  makewild(dwild, lst);
                  dpath = ".";
            } else {
                  makewild(dwild, lst+1);
                  dpath = xpath;
                  lst[1] = 0;
            }
            opt_d = 0;
      } else {
            dpath = xpath;
            strcpy(dwild, "\377*");
      }
      err = NWParsePath(dpath, NULL, &conn, volname, dirpath);
      if (err) {
            fprintf(stderr, _("Invalid path: %s\n"), strnwerror(err));
            return 123;
      }
      if (!conn) {
            fprintf(stderr, _("Specified path is not remote\n"));
            return 123;
      }
      xpath = dirpath;
      for (path=xpath; *path; path++) {
            *path = toupper(*path);
      }
      if (*volname) {
            sprintf(fullpath, "%s:%s", volname, dirpath);
      } else {
            strcpy(fullpath, dirpath);
      }
      printf(_("Directory %s\n"), fullpath);

      err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL, NCP_DIRSTYLE_NOHANDLE, 0, 0, 
                  fullpath, NCP_PATH_STD, NW_NS_DOS, RIM_ATTRIBUTES | RIM_DIRECTORY, 
                  &dosNS2, sizeof(dosNS2));
      if (err) {
            fprintf(stderr, _("Path does not exist: %s\n"), strnwerror(err));
            return 123;
      }
      img = RIM_NAME | RIM_ATTRIBUTES | RIM_DIRECTORY;
      if (opt_l) {
            img |= RIM_OWNING_NAMESPACE;
      }
      if (opt_v) {
            img |= RIM_SPACE_ALLOCATED | RIM_DATA_SIZE |
                   RIM_ARCHIVE | RIM_MODIFY | RIM_CREATION |
                   RIM_OWNING_NAMESPACE | RIM_RIGHTS;
      }
      err = NWGetFileServerVersion(conn, &nwver);
      if (err) {
            nwver = 0;
      }
      if (nwver >= 0x400) {
            img |= RIM_COMPRESSED_INFO;
            if (opt_v) {
                  img |= RIM_DATASTREAM_SIZES | RIM_DATASTREAM_LOGICALS;
            }
      }
      if (nwver >= 0x40B) {
            if (opt_v) {
                  img |= RIM_MAC_FINDER_INFO | RIM_EFFECTIVE_RIGHTS |
                         RIM_MAC_TIMES;
            }
      }
      if (nwver >= 0x500) {
            if (opt_v) {
                  img |= RIM_LAST_ACCESS_TIME;
            }
      }
      if ((dosNS2.Attributes.Attributes & A_DIRECTORY) && !opt_d) {
            listdir(conn, dosNS2.Directory.volNumber, dosNS2.Directory.DosDirNum, dwild);
      } else {
            struct nw_info_struct3 info;

            info.len = 0;
            info.data = NULL;

            err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL, 
                  1, dosNS2.Directory.volNumber, dosNS2.Directory.DosDirNum,
                  NULL, 0,
                  NW_NS_DOS,
                  IM_ALL,
                  &info, sizeof(info));
            if (err) {
                  fprintf(stderr, _("Cannot retrieve info: %s\n"), strnwerror(err));
            } else {
                  dumpit(conn, &info);
                  free(info.data);
            }
      }
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index