source: umon/main/common/tfsapi.c @ 87db514

Last change on this file since 87db514 was 87db514, checked in by Amar Takhar <amar@…>, on 04/16/15 at 19:26:21

Initial commit of the umon repository.

Prior to this three changes were made:

  • Remove umon_ prefix from parent directories.
  • Collapse main/target/ into main/
  • Remove ports/template/flashtest.scr.ucon script.
  • Property mode set to 100644
File size: 15.4 KB
Line 
1/**************************************************************************
2 *
3 * Copyright (c) 2013 Alcatel-Lucent
4 *
5 * Alcatel Lucent licenses this file to You under the Apache License,
6 * Version 2.0 (the "License"); you may not use this file except in
7 * compliance with the License.  A copy of the License is contained the
8 * file LICENSE at the top level of this repository.
9 * You may also obtain a copy of the License at:
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 **************************************************************************
20 *
21 * tfsapi.c:
22 *
23 * This file contains the portion of TFS that provides the function-level
24 * API to the application.  If this is not being used by the application
25 * then it can be omitted from the monitor build.
26 * Note that not all of the api-specific code is here; some of it is in
27 * tfs.c.  This is because the the MicroMonitor uses some of the api itself,
28 * so it cannot be omitted from the TFS package without screwing up some
29 * other monitor functionality that needs it.
30 *
31 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
32 *
33 */
34#include "config.h"
35#include "cpu.h"
36#include "stddefs.h"
37#include "genlib.h"
38#include "tfs.h"
39#include "tfsprivate.h"
40#if INCLUDE_TFSAPI
41
42/* tfstruncate():
43 *      To support the ability to truncate a file (make it smaller); this
44 *      function allows the user to adjust the high-water point of the currently
45 *      opened (and assumed to be opened for modification) file and replaces
46 *      that with the incoming argument.  This replacement is only done if the
47 *      current high-water point is higher than the incoming length.
48 *      MONLIB NOTICE: this function is accessible through monlib.c.
49 */
50int
51tfstruncate(int fd, long len)
52{
53        struct tfsdat *tdat;
54
55        if (tfsTrace > 1)
56                printf("tfstruncate(%d,%ld)\n",fd,len);
57
58        /* Verify valid range of incoming file descriptor. */
59        if ((fd < 0) || (fd >= TFS_MAXOPEN))
60                return(TFSERR_BADFD);
61
62        tdat = &tfsSlots[fd];
63
64        /* Make sure the file pointed to by the incoming descriptor is active
65         * and that the incoming length is greater than the current high-water
66         * point...
67         */
68        if (tdat->offset == -1)
69                return(TFSERR_BADFD);
70        if (len > tdat->hwp)
71                return(TFSERR_BADARG);
72
73        /* Make the adjustment... */
74        tdat->hwp = len;
75        return(TFS_OKAY);
76}
77
78/* tfseof():
79 *      Return 1 if at the end of the file, else 0 if not at end; else negative
80 *      if error.
81 *      MONLIB NOTICE: this function is accessible through monlib.c.
82 */
83int
84tfseof(int fd)
85{
86        struct tfsdat *tdat;
87
88        /* Verify valid range of incoming file descriptor. */
89        if ((fd < 0) || (fd >= TFS_MAXOPEN))
90                return(TFSERR_BADARG);
91
92        tdat = &tfsSlots[fd];
93
94        /* Make sure the file pointed to by the incoming descriptor is active. */
95        if (tdat->offset == -1)
96                return(TFSERR_BADFD);
97
98        if (tdat->offset >= tdat->hdr.filsize)
99                return(1);
100        else
101                return(0);
102}
103
104/* tfsread():
105 *      Similar to a standard read call to a file.
106 *      MONLIB NOTICE: this function is accessible through monlib.c.
107 */
108int
109tfsread(int fd, char *buf, int cnt)
110{
111        struct tfsdat *tdat;
112        uchar *from;
113
114        if (tfsTrace > 1)
115                printf("tfsread(%d,0x%lx,%d)\n",fd,(ulong)buf,cnt);
116
117        /* Verify valid range of incoming file descriptor. */
118        if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN))
119                return(TFSERR_BADARG);
120
121        tdat = &tfsSlots[fd];
122
123        /* Make sure the file pointed to by the incoming descriptor is active. */
124        if (tdat->offset == -1)
125                return(TFSERR_BADFD);
126
127        if (tdat->offset >= tdat->hdr.filsize)
128                return(TFSERR_EOF);
129
130        from = (uchar *) tdat->base + tdat->offset;
131
132        /* If request size is within the range of the file and current
133         * then copy the data to the requestors buffer, increment offset
134         * and return the count.
135         */
136        if ((tdat->offset + cnt) <= tdat->hdr.filsize) {
137                if (s_memcpy((char *)buf, (char *)from, cnt,0,0) != 0)
138                        return(TFSERR_MEMFAIL);
139        }
140        /* If request size goes beyond the size of the file, then copy
141         * to the end of the file and return that smaller count.
142         */
143        else {
144                cnt = tdat->hdr.filsize - tdat->offset;
145                if (s_memcpy((char *)buf, (char *)from, cnt, 0, 0) != 0)
146                        return(TFSERR_MEMFAIL);
147        }
148        tdat->offset += cnt;
149        return(cnt);
150}
151
152/* tfswrite():
153 *      Similar to a standard write call to a file.
154 *      MONLIB NOTICE: this function is accessible through monlib.c.
155 */
156int
157tfswrite(int fd, char *buf, int cnt)
158{
159        struct tfsdat *tdat;
160
161        if (tfsTrace > 1)
162                printf("tfswrite(%d,0x%lx,%d)\n", fd,(ulong)buf,cnt);
163
164        /* Verify valid range of incoming file descriptor. */
165        if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN))
166                return(TFSERR_BADARG);
167
168        /* Make sure the file pointed to by the incoming descriptor is active. */
169        if (tfsSlots[fd].offset == -1)
170                return(TFSERR_BADARG);
171
172        tdat = &tfsSlots[fd];
173
174        /* Make sure file is not opened as read-only */
175        if (tdat->flagmode & TFS_RDONLY)
176                return(TFSERR_RDONLY);
177
178        if (s_memcpy((char *)tdat->base+tdat->offset,(char *)buf,cnt,0,0) != 0)
179                return(TFSERR_MEMFAIL);
180
181        tdat->offset += cnt;
182
183        /* If new offset is greater than current high-water point, then
184         * adjust the high water point so that it is always reflecting the
185         * highest offset into which the file has had some data written.
186         */
187        if (tdat->offset > tdat->hwp)
188                tdat->hwp = tdat->offset;
189
190        return(TFS_OKAY);
191}
192
193/* tfsseek():
194 *      Adjust the current pointer into the specified file.
195 *      If file is read-only, then the offset cannot exceed the file size;
196 *      otherwise, the only check made to the offset is that it is positive.
197 *      MONLIB NOTICE: this function is accessible through monlib.c.
198 */
199int
200tfsseek(int fd, int offset, int whence)
201{
202        int     o_offset;
203        struct tfsdat *tdat;
204
205        if (tfsTrace > 1)
206                printf("tfsseek(%d,%d,%d)\n",fd,offset,whence);
207
208        if ((fd < 0) || (fd >= TFS_MAXOPEN))
209                return(TFSERR_BADARG);
210
211        tdat = &tfsSlots[fd];
212        o_offset = tdat->offset;
213
214        switch (whence) {
215                case TFS_BEGIN:
216                        tdat->offset = offset;
217                        break;
218                case TFS_CURRENT:
219                        tdat->offset += offset;
220                        break;
221                default:
222                        return(TFSERR_BADARG);
223        }
224
225        /* If new offset is less than zero or if the file is read-only and the
226         * new offset is greater than the file size, return EOF...
227         */
228        if ((tdat->offset < 0) ||
229                ((tdat->flagmode & TFS_RDONLY) && (tdat->offset > tdat->hdr.filsize))){
230                tdat->offset = o_offset;
231                return(TFSERR_EOF);
232        }
233        return(tdat->offset);
234}
235
236/* tfsipmod():
237 *      Modify "in-place" a portion of a file in TFS.
238 *      This is a cheap and dirty way to modify a file...
239 *      The idea is that a file is created with a lot of writeable flash space
240 *      (data = 0xff).  This function can then be called to immediately modify
241 *      blocks of space in that flash.  It will not do any tfsunlink/tfsadd, and
242 *      it doesn't even require a tfsopen() tfsclose() wrapper.  Its a fast and
243 *      efficient way to modify flash in the file system.
244 *      Arguments:
245 *      name    =       name of the file to be in-place-modified;
246 *      buf             =       new data to be written to flash;
247 *      offset  =       offset into file into which new data is to be written;
248 *      size    =       size of new data (in bytes).
249 *     
250 *      With offset of -1, set offset to location containing first 0xff value.
251 *      MONLIB NOTICE: this function is accessible through monlib.c.
252 */
253int
254tfsipmod(char *name,char *buf,int offset,int size)
255{
256        int             rc;
257        TFILE   *fp;
258        uchar   *cp;
259
260        fp = tfsstat(name);
261        if (!fp)
262                return (TFSERR_NOFILE);
263        if (!(fp->flags & TFS_IPMOD))
264                return(TFSERR_NOTIPMOD);
265       
266        if (offset == -1) {
267                cp = (uchar *)(TFS_BASE(fp));
268                for (offset=0;offset<fp->filsize;offset++,cp++) {
269                        if (*cp == 0xff)
270                                break;
271                }
272        }
273        else if (offset < -1)
274                return(TFSERR_BADARG);
275       
276        if ((offset + size) > fp->filsize)
277                return(TFSERR_WRITEMAX);
278       
279        /* BUG fixed: 2/21/2001:
280         * The (ulong *) cast was done prior to adding offset to the base.
281         * This caused the offset to be quadrupled.
282         */
283        rc = tfsflashwrite((uchar *)(TFS_BASE(fp)+offset),(uchar *)buf,size);
284        if (rc != TFS_OKAY)
285                return(rc);
286
287        tfslog(TFSLOG_IPM,name);
288        return(TFS_OKAY);
289}
290
291/* tfsopen():
292 *      Open a file for reading or creation.  If file is opened for writing,
293 *      then the caller must provide a RAM buffer  pointer to be used for
294 *      the file storage until it is transferred to flash by tfsclose().
295 *      Note that the "buf" pointer is only needed for opening a file for
296 *      creation or append (writing).
297 *      MONLIB NOTICE: this function is accessible through monlib.c.
298 */
299int
300tfsopen(char *file,long flagmode,char *buf)
301{
302        register int i;
303        int             errno, retval;
304        long    fmode;
305        TFILE   *fp;
306        struct  tfsdat *slot;
307
308        errno = TFS_OKAY;
309
310        fmode = flagmode & (TFS_RDONLY | TFS_APPEND | TFS_CREATE | TFS_CREATERM);
311
312        /* See if file exists... */
313        fp = tfsstat(file);
314
315        /* If file exists, do a crc32 on the data.
316         * If the file is in-place-modifiable, then the only legal flagmode
317         * is TFS_RDONLY.  Plus, in this case, the crc32 test is skipped.
318         */
319        if (fp) {
320                if (!((fmode == TFS_RDONLY) && (fp->flags & TFS_IPMOD))) {
321                        if (crc32((unsigned char *)TFS_BASE(fp),fp->filsize) != fp->filcrc) {
322                                retval = TFSERR_BADCRC;
323                                goto done;
324                        }
325                }
326        }
327
328        /* This switch verifies...
329         * - that the file exists if TFS_RDONLY or TFS_APPEND
330         * - that the file does not exist if TFS_CREATE
331         */
332        switch(fmode) {
333        case TFS_RDONLY:        /* Read existing file only, no change to file at all. */
334                if (!fp) {
335                        if (_tfsstat(file,0))
336                                errno = TFSERR_LINKERROR;
337                        else
338                        errno = TFSERR_NOFILE;
339                }
340                else {
341                        if ((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp) > getUsrLvl()))
342                                errno = TFSERR_USERDENIED;
343                }
344                break;
345        case TFS_APPEND:        /* Append to the end of the current file. */
346                if (!fp)
347                        errno = TFSERR_NOFILE;
348                else {
349                        if (TFS_USRLVL(fp) > getUsrLvl())
350                                errno = TFSERR_USERDENIED;
351                }
352                break;
353        case TFS_CREATERM:              /* Create a new file, allow tfsadd() to remove */
354                fmode = TFS_CREATE;     /* it if it exists. */
355                break;         
356        case TFS_CREATE:        /* Create a new file, error if it exists. */
357                if (fp)
358                        errno = TFSERR_FILEEXISTS;
359                break;
360        case (TFS_APPEND|TFS_CREATE):   /* If both mode bits are set, clear one */
361                if (fp) {                                       /* based on the presence of the file. */
362                        if (TFS_USRLVL(fp) > getUsrLvl())
363                                errno = TFSERR_USERDENIED;
364                        fmode = TFS_APPEND;
365                }
366                else {
367                        fmode = TFS_CREATE;
368                }
369                break;
370        default:
371                errno = TFSERR_BADARG;
372                break;
373        }
374
375        if (errno != TFS_OKAY) {
376                retval = errno;
377                goto done;
378        }
379
380        /* Find an empty slot...
381         */
382        slot = tfsSlots;
383        for (i=0;i<TFS_MAXOPEN;i++,slot++) {
384                if (slot->offset == -1)
385                        break;
386        }
387
388        /* Populate the slot structure if a slot is found to be
389         * available...
390         */
391        if (i < TFS_MAXOPEN) {
392                retval = i;
393                slot->hwp = 0;
394                slot->offset = 0;
395                slot->flagmode = fmode;
396                if (fmode & TFS_CREATE) {
397                        strncpy(slot->hdr.name,file,TFSNAMESIZE);
398                        slot->flagmode |= (flagmode & TFS_FLAGMASK);
399                        slot->base = (uchar *)buf;
400                }
401                else if (fmode & TFS_APPEND) {
402                        memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr));
403                        if (s_memcpy((char *)buf,(char *)(TFS_BASE(fp)),
404                                fp->filsize,0,0) != 0) {
405                                retval = TFSERR_MEMFAIL;
406                                goto done;
407                        }
408                        slot->flagmode = fp->flags;
409                        slot->flagmode |= TFS_APPEND;
410                        slot->base = (uchar *)buf;
411                        slot->hwp = fp->filsize;
412                        slot->offset = fp->filsize;
413                }
414                else {
415                        slot->base = (uchar *) (TFS_BASE(fp));
416                        memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr));
417                }
418        }
419        else {
420                retval = TFSERR_NOSLOT;
421        }
422
423done:           
424        if (tfsTrace > 0)
425                printf("tfsopen(%s,0x%lx,0x%lx)=%d\n",file,flagmode,(ulong)buf,retval);
426
427        return(retval);
428}
429
430/* tfsclose():
431 *      If the file was opened for reading only, then just close out the
432 *      entry in the tfsSlots table.  If the file was opened for creation,
433 *      then add it to the tfs list.  Note the additional argument is
434 *      only needed for tfsclose() of a newly created file.
435 *      info  = additional text describing the file.
436 *      MONLIB NOTICE: this function is accessible through monlib.c.
437 */
438int
439tfsclose(int fd,char *info)
440{
441        int             err;
442        struct tfsdat *tdat;
443
444        if (!info) info = "";
445
446        if (tfsTrace > 0)
447                printf("tfsclose(%d,%s)\n",fd,info);
448
449        if ((fd < 0) || (fd >= TFS_MAXOPEN))
450                return(TFSERR_BADARG);
451
452        tdat = &tfsSlots[fd];
453
454        if (tdat->offset == -1)
455                return(TFSERR_BADFD);
456
457        /* Mark the file as closed by setting the offset to -1.
458         * Note that this is done prior to potentially calling tfsadd() so
459         * that tfsadd() will not think the file is opened and reject the add...
460         */
461        tdat->offset = -1;
462
463        /* If the file was opened for creation or append, and the hwp
464         * (high-water-point) is greater than zero, then add it now.
465         *
466         * Note regarding hwp==0...
467         * In cases where a non-existent file is opened for creation,
468         * but then nothing is written to the file, the hwp value will
469         * be zero; hence, no need to call tfsadd().
470         */
471        if ((tdat->flagmode & (TFS_CREATE | TFS_APPEND)) && (tdat->hwp > 0)) {
472                char    buf[16];
473
474                err = tfsadd(tdat->hdr.name, info, tfsflagsbtoa(tdat->flagmode,buf),
475                        tdat->base, tdat->hwp);
476                if (err != TFS_OKAY) {
477                        printf("%s: %s\n",tdat->hdr.name,tfserrmsg(err));
478                        return(err);
479                }
480        }
481        return(TFS_OKAY);
482}
483
484#else /* INCLUDE_TFSAPI */
485
486int
487tfstruncate(int fd, long len)
488{
489        return(TFSERR_NOTAVAILABLE);
490}
491
492int
493tfseof(int fd)
494{
495        return(TFSERR_NOTAVAILABLE);
496}
497
498int
499tfsread(int fd, char *buf, int cnt)
500{
501        return(TFSERR_NOTAVAILABLE);
502}
503
504int
505tfswrite(int fd, char *buf, int cnt)
506{
507        return(TFSERR_NOTAVAILABLE);
508}
509
510int
511tfsseek(int fd, int offset, int whence)
512{
513        return(TFSERR_NOTAVAILABLE);
514}
515
516int
517tfsopen(char *file,long flagmode,char *buf)
518{
519        return(TFSERR_NOTAVAILABLE);
520}
521
522int
523tfsclose(int fd,char *info)
524{
525        return(TFSERR_NOTAVAILABLE);
526}
527
528int
529tfsipmod(char *name,char *buf,int offset,int size)
530{
531        return(TFSERR_NOTAVAILABLE);
532}
533
534#endif  /* INCLUDE_TFSAPI else */
535
536#if INCLUDE_TFSAPI || INCLUDE_TFSSCRIPT
537
538/* tfsgetline():
539 *      Read into the buffer a block of characters upto the next EOL delimiter
540 *      the file.  After the EOL, or after max-1 chars are loaded, terminate
541 *      with a NULL.  Return the number of characters loaded.
542 *      At end of file return 0.
543 *      MONLIB NOTICE: this function is accessible through monlib.c.
544 */
545int
546tfsgetline(int fd,char *buf,int max)
547{
548        uchar   *from;
549        int             tot, rtot;
550        struct  tfsdat *tdat;
551        volatile char   *to;
552
553        max--;
554
555        if (tfsTrace > 1)
556                printf("tfsgetline(%d,0x%lx,%d)\n",fd,(ulong)buf,max);
557
558        /* Verify valid range of incoming file descriptor. */
559        if ((max < 1) || (fd < 0) || (fd >= TFS_MAXOPEN))
560                return(TFSERR_BADARG);
561
562        /* Make sure the file pointed to by the incoming descriptor is active. */
563        if (tfsSlots[fd].offset == -1)
564                return(TFSERR_BADARG);
565
566        tdat = &tfsSlots[fd];
567
568        if (tdat->offset == -1)
569                return(TFSERR_BADFD);
570
571        if (tdat->offset >= tdat->hdr.filsize)
572                return(0);
573
574        from = (uchar *) tdat->base + tdat->offset;
575        to = buf;
576
577        /* If the incoming buffer size is larger than needed, adjust the
578         * 'max' value so that we don't pass the end of the file...
579         */
580        if ((tdat->offset + max) > tdat->hdr.filsize)
581                max = tdat->hdr.filsize - tdat->offset + 1;
582
583        /* Read from the file data area until newline (0x0a) is found
584         * (or until the 'max buffer space' value is reached).
585         * Strip 0x0d (if present) and terminate with NULL  in all cases. 
586         */
587        for(rtot=0,tot=0;tot < max; from++) {
588                /* Terminate on Ctrl-Z, non-ASCII, Newline or NULL.
589                 * Ignore carriage return completely...
590                 */
591                if ((*from == 0x1a) || (*from > 0x7f) || (*from == 0))         
592                        break;
593
594                tot++;
595
596                if (*from == 0x0d)
597                        continue;
598
599                *to = *from;
600                if (*to != *from)
601                        return(TFSERR_MEMFAIL);
602
603                to++; rtot++;
604
605                if (*from == 0x0a)
606                        break;
607        }
608        *to = 0;
609
610        tdat->offset += tot;
611        return(rtot);
612}
613
614#else
615
616int
617tfsgetline(int fd,char *buf,int max)
618{
619        return(TFSERR_NOTAVAILABLE);
620}
621
622#endif
Note: See TracBrowser for help on using the repository browser.