View Javadoc

1   /*
2    * Copyright (c) 2005 The University of Reading
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    * 1. Redistributions of source code must retain the above copyright
9    *    notice, this list of conditions and the following disclaimer.
10   * 2. Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in the
12   *    documentation and/or other materials provided with the distribution.
13   * 3. Neither the name of the University of Reading, nor the names of the
14   *    authors or contributors may be used to endorse or promote products
15   *    derived from this software without specific prior written permission.
16   * 
17   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   */
28  
29  package uk.ac.rdg.resc.jstyx.types;
30  
31  import java.util.Date;
32  import java.util.Calendar;
33  import java.text.SimpleDateFormat;
34  
35  import uk.ac.rdg.resc.jstyx.StyxUtils;
36  
37  /***
38   * A directory entry on a Styx server (i.e. a file stat)
39   *
40   * @author Jon Blower
41   * $Revision: 604 $
42   * $Date: 2006-03-21 14:58:42 +0000 (Tue, 21 Mar 2006) $
43   * $Log$
44   * Revision 1.3  2006/03/21 14:58:42  jonblower
45   * Implemented clear-text password-based authentication and did some simple tests
46   *
47   * Revision 1.2  2005/11/28 17:18:00  jonblower
48   * Changed comments to explain type, dev and DMEXCL
49   *
50   * Revision 1.1.1.1  2005/02/16 18:58:35  jonblower
51   * Initial import
52   *
53   */
54  public class DirEntry
55  {
56      // A stat message contains a 2-byte dirEntrySize that is not included in
57      // this class: it is calculated automatically when needed
58      private int type;              // 2 bytes, for kernel use
59      private long dev;              // 4 bytes, for kernel use
60      private Qid qid;               // the server's representation of this file
61      private long mode;             // 4 bytes, permissions and flags
62      private long lastAccessTime;   // 4 bytes, last access time (seconds since the epoch)
63      private long lastModifiedTime; // 4 bytes, last modification time (seconds since the epoch)
64      private ULong fileLength;      // length of file in bytes (8 bytes)
65      private String fileName;       // file name
66      private String owner;         // owner name
67      private String group;        // group name
68      private String lastModifiedBy; // name of the user who last modified the file
69      
70      /*** 
71       * Creates a new instance of DirEntry.
72       * This constructor is most useful when parsing an RstatMessage or similar
73       */
74      public DirEntry(int type, long dev, Qid qid, long mode,
75          long lastAccessTime, long lastModifiedTime, ULong fileLength,
76          String fileName, String owner, String group, String lastModifiedBy)
77      {
78          this.type = type;
79          this.dev = dev;
80          this.qid = qid;
81          this.mode = mode;
82          this.lastAccessTime = lastAccessTime;
83          this.lastModifiedTime = lastModifiedTime;
84          this.fileLength = fileLength;
85          this.fileName = fileName;
86          this.owner = owner;
87          this.group = group;
88          this.lastModifiedBy = lastModifiedBy;
89      }
90      
91      /***
92       * This constructor is most useful when creating a DirEntry from a StyxFile
93       */
94      public DirEntry(Qid qid, long mode, long lastAccessTime, long lastModifiedTime,
95          ULong fileLength, String fileName, String owner, String group, 
96          String lastModifiedBy)
97      {
98          this.type = 0;  // The type and dev are not needed in JStyx: they are
99          this.dev = 0;   // used to distinguish devices in Inferno / Plan9
100         this.qid = qid;
101         this.mode = mode;
102         this.lastAccessTime = lastAccessTime;
103         this.lastModifiedTime = lastModifiedTime;
104         this.fileLength = fileLength;
105         this.fileName = fileName;
106         this.owner = owner;
107         this.group = group;
108         this.lastModifiedBy = lastModifiedBy;
109     }
110     
111     public String toString()
112     {
113         return type + ", " + dev + ", " + qid + ", " +
114             mode + ", " + lastAccessTime + ", " + lastModifiedTime + ", " +
115             fileLength + ", " + fileName + ", " + owner + ", " + group +
116             ", " + lastModifiedBy;
117     }
118     
119     /***
120      * Gets the file permissions as a string (e.g. "drwxr-xr-x")
121      */
122     public String getPermissionsAsString()
123     {
124         StringBuffer s = new StringBuffer();
125         if ((this.mode & StyxUtils.DMDIR) == StyxUtils.DMDIR)
126         {
127             s.append("d");
128         }
129         else if ((this.mode & StyxUtils.DMAPPEND) == StyxUtils.DMAPPEND)
130         {
131             s.append("a");
132         }
133         else if ((this.mode & StyxUtils.DMAUTH) == StyxUtils.DMAUTH)
134         {
135             s.append("A");
136         }
137         else
138         {
139             s.append("-");
140         }
141         if ((this.mode & StyxUtils.DMEXCL) == StyxUtils.DMEXCL)
142         {
143             s.append("l");; // "l" stands for "lock"
144         }
145         else
146         {
147             s.append("-");
148         }
149         int operm = (int)(this.mode & 1023);
150         s.append(getPerms(operm >> 6)); // owner permissions
151         s.append(getPerms(operm >> 3)); // group permissions
152         s.append(getPerms(operm));      // everyone permissions
153         return s.toString();
154     }
155     
156     /***
157      * Formats the dirEntry as a string similar to how it appears with an
158      * "ls -l" command in Inferno
159      */
160     public String asLsEntry()
161     {
162         StringBuffer s = new StringBuffer(this.getPermissionsAsString());
163         
164         // We shan't print out the device type or device instance number
165         
166         s.append(" " + this.owner + " " + this.group + " " + this.fileLength + " ");
167         
168         // Now format the last modified time as in Inferno
169         Date lmt = new Date(this.lastModifiedTime * 1000);
170         // Format the date as, e.g. "Nov 11 08:23" or "Nov 11 2003" if the year
171         // is not the current year
172         Calendar cal = Calendar.getInstance();
173         int currentYear = cal.get(Calendar.YEAR);
174         cal.setTime(lmt);
175         int fileYear = cal.get(Calendar.YEAR);
176         String fmtStr;
177         if (currentYear == fileYear)
178         {
179             fmtStr = "MMM d HH:mm";
180         }
181         else
182         {
183             fmtStr = "MMM d  yyyy";
184         }
185         // TODO: if the year is not the current year, should we display this?
186         SimpleDateFormat formatter = new SimpleDateFormat(fmtStr);
187         s.append(formatter.format(lmt));
188         
189         s.append(" " + this.fileName);
190         
191         return s.toString();
192     }
193     
194     private String getPerms(int perm)
195     {
196         // Mask off the last three bits
197         perm = perm & 7;
198         switch(perm)
199         {
200             case 0:
201                 return "---";
202             case 1:
203                 return "--x";
204             case 2:
205                 return "-w-";
206             case 3:
207                 return "-wx";
208             case 4:
209                 return "r--";
210             case 5:
211                 return "r-x";
212             case 6:
213                 return "rw-";
214             case 7:
215                 return "rwx";
216             default:
217                 throw new IllegalArgumentException("perm argument must be in the range 0-7");
218         }
219     }
220     
221     /***
222      * Gets the total size of the DirEntry, including the two-byte size field
223      * at the start of the stat entry.
224      */
225     public int getSize()
226     {
227         int len = 2 + 2 + 4 + 13 + 4 + 4 + 4 + 8;
228         // Count the length of the string quantities
229         len += StyxUtils.strToUTF8(this.fileName).length + 2;
230         len += StyxUtils.strToUTF8(this.owner).length + 2;
231         len += StyxUtils.strToUTF8(this.group).length + 2;
232         len += StyxUtils.strToUTF8(this.lastModifiedBy).length + 2;
233         return len;
234     }
235     
236     public int getType()
237     {
238         return type;
239     }
240     
241     public void setType(int type)
242     {
243         this.type = type;
244     }
245     
246     public long getDev()
247     {
248         return dev;
249     }
250     
251     public void setDev(long dev)
252     {
253         this.dev = dev;
254     }
255     
256     public Qid getQid()
257     {
258         return qid;
259     }
260     
261     public void setQid(Qid qid)
262     {
263         this.qid = qid;
264     }
265     
266     public long getMode()
267     {
268         return mode;
269     }
270     
271     public void setMode(long mode)
272     {
273         this.mode = mode;
274     }
275     
276     public long getLastAccessTime()
277     {
278         return lastAccessTime;
279     }
280     
281     public void setLastAccessTime(long lastAccessTime)
282     {
283         this.lastAccessTime = lastAccessTime;
284     }
285     
286     public long getLastModifiedTime()
287     {
288         return lastModifiedTime;
289     }
290     
291     public void setLastModifiedTime(long lastModifiedTime)
292     {
293         this.lastModifiedTime = lastModifiedTime;
294     }
295     
296     public ULong getFileLength()
297     {
298         return fileLength;
299     }
300     
301     public void setFileLength(ULong fileLength)
302     {
303         this.fileLength = fileLength;
304     }
305     
306     public String getFileName()
307     {
308         return fileName;
309     }
310     
311     public void setFileName(String fileName)
312     {
313         this.fileName = fileName;
314     }
315     
316     public String getOwner()
317     {
318         return owner;
319     }
320     
321     public void setOwner(String owner)
322     {
323         this.owner = owner;
324     }
325     
326     public String getGroup()
327     {
328         return group;
329     }
330     
331     public void setGroup(String group)
332     {
333         this.group = group;
334     }
335     
336     public String getLastModifiedBy()
337     {
338         return lastModifiedBy;
339     }
340     
341     public void setLastModifiedBy(String lastModifiedBy)
342     {
343         this.lastModifiedBy = lastModifiedBy;
344     }
345     
346 }