Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/macosx/tclMacOSXFCmd.c @ 37

Last change on this file since 37 was 25, checked in by landauf, 17 years ago

added tcl to libs

File size: 18.2 KB
Line 
1/*
2 * tclMacOSXFCmd.c
3 *
4 *      This file implements the MacOSX specific portion of file manipulation
5 *      subcommands of the "file" command.
6 *
7 * Copyright (c) 2003-2007 Daniel A. Steffen <das@users.sourceforge.net>
8 *
9 * See the file "license.terms" for information on usage and redistribution of
10 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 *
12 * RCS: @(#) $Id: tclMacOSXFCmd.c,v 1.12 2007/04/23 20:46:14 das Exp $
13 */
14
15#include "tclInt.h"
16
17#ifdef HAVE_GETATTRLIST
18#include <sys/attr.h>
19#include <sys/paths.h>
20#include <libkern/OSByteOrder.h>
21#endif
22
23/* Darwin 8 copyfile API. */
24#ifdef HAVE_COPYFILE
25#ifdef HAVE_COPYFILE_H
26#include <copyfile.h>
27#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
28/* Support for weakly importing copyfile. */
29#define WEAK_IMPORT_COPYFILE
30extern int copyfile(const char *from, const char *to, copyfile_state_t state,
31                    copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE;
32#endif /* HAVE_WEAK_IMPORT */
33#else /* HAVE_COPYFILE_H */
34int copyfile(const char *from, const char *to, void *state, uint32_t flags);
35#define COPYFILE_ACL            (1<<0)
36#define COPYFILE_XATTR          (1<<2)
37#define COPYFILE_NOFOLLOW_SRC   (1<<18)
38#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
39/* Support for weakly importing copyfile. */
40#define WEAK_IMPORT_COPYFILE
41extern int copyfile(const char *from, const char *to, void *state,
42                    uint32_t flags) WEAK_IMPORT_ATTRIBUTE;
43#endif /* HAVE_WEAK_IMPORT */
44#endif /* HAVE_COPYFILE_H */
45#endif /* HAVE_COPYFILE */
46
47#include <libkern/OSByteOrder.h>
48
49/*
50 * Constants for file attributes subcommand. Need to be kept in sync with
51 * tclUnixFCmd.c !
52 */
53
54enum {
55    UNIX_GROUP_ATTRIBUTE,
56    UNIX_OWNER_ATTRIBUTE,
57    UNIX_PERMISSIONS_ATTRIBUTE,
58#ifdef HAVE_CHFLAGS
59    UNIX_READONLY_ATTRIBUTE,
60#endif
61#ifdef MAC_OSX_TCL
62    MACOSX_CREATOR_ATTRIBUTE,
63    MACOSX_TYPE_ATTRIBUTE,
64    MACOSX_HIDDEN_ATTRIBUTE,
65    MACOSX_RSRCLENGTH_ATTRIBUTE,
66#endif
67};
68
69typedef u_int32_t OSType;
70
71static int              GetOSTypeFromObj(Tcl_Interp *interp,
72                            Tcl_Obj *objPtr, OSType *osTypePtr);
73static Tcl_Obj *        NewOSTypeObj(const OSType newOSType);
74static int              SetOSTypeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
75static void             UpdateStringOfOSType(Tcl_Obj *objPtr);
76
77static Tcl_ObjType tclOSTypeType = {
78    "osType",                           /* name */
79    NULL,                               /* freeIntRepProc */
80    NULL,                               /* dupIntRepProc */
81    UpdateStringOfOSType,               /* updateStringProc */
82    SetOSTypeFromAny                    /* setFromAnyProc */
83};
84
85enum {
86   kIsInvisible = 0x4000,
87};
88
89#define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible))
90
91typedef struct finderinfo {
92    u_int32_t type;
93    u_int32_t creator;
94    u_int16_t fdFlags;
95    u_int32_t location;
96    u_int16_t reserved;
97    u_int32_t extendedFileInfo[4];
98} __attribute__ ((__packed__)) finderinfo;
99
100typedef struct fileinfobuf {
101    u_int32_t info_length;
102    u_int32_t data[8];
103} fileinfobuf;
104
105/*
106 *----------------------------------------------------------------------
107 *
108 * TclMacOSXGetFileAttribute
109 *
110 *      Gets a MacOSX attribute of a file. Which attribute is controlled by
111 *      objIndex. The object will have ref count 0.
112 *
113 * Results:
114 *      Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
115 *      is no error.
116 *
117 * Side effects:
118 *      A new object is allocated.
119 *
120 *----------------------------------------------------------------------
121 */
122
123int
124TclMacOSXGetFileAttribute(
125    Tcl_Interp *interp,          /* The interp we are using for errors. */
126    int objIndex,                /* The index of the attribute. */
127    Tcl_Obj *fileName,           /* The name of the file (UTF-8). */
128    Tcl_Obj **attributePtrPtr)   /* A pointer to return the object with. */
129{
130#ifdef HAVE_GETATTRLIST
131    int result;
132    Tcl_StatBuf statBuf;
133    struct attrlist alist;
134    fileinfobuf finfo;
135    finderinfo *finder = (finderinfo*)(&finfo.data);
136    off_t *rsrcForkSize = (off_t*)(&finfo.data);
137    const char *native;
138
139    result = TclpObjStat(fileName, &statBuf);
140
141    if (result != 0) {
142        Tcl_AppendResult(interp, "could not read \"",
143                TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
144        return TCL_ERROR;
145    }
146
147    if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) {
148        /*
149         * Directories only support attribute "-hidden".
150         */
151
152        errno = EISDIR;
153        Tcl_AppendResult(interp, "invalid attribute: ",
154                Tcl_PosixError(interp), NULL);
155        return TCL_ERROR;
156    }
157
158    bzero(&alist, sizeof(struct attrlist));
159    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
160    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
161        alist.fileattr = ATTR_FILE_RSRCLENGTH;
162    } else {
163        alist.commonattr = ATTR_CMN_FNDRINFO;
164    }
165    native = Tcl_FSGetNativePath(fileName);
166    result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);
167
168    if (result != 0) {
169        Tcl_AppendResult(interp, "could not read attributes of \"",
170                TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
171        return TCL_ERROR;
172    }
173
174    switch (objIndex) {
175    case MACOSX_CREATOR_ATTRIBUTE:
176        *attributePtrPtr = NewOSTypeObj(
177                OSSwapBigToHostInt32(finder->creator));
178        break;
179    case MACOSX_TYPE_ATTRIBUTE:
180        *attributePtrPtr = NewOSTypeObj(
181                OSSwapBigToHostInt32(finder->type));
182        break;
183    case MACOSX_HIDDEN_ATTRIBUTE:
184        *attributePtrPtr = Tcl_NewBooleanObj(
185                (finder->fdFlags & kFinfoIsInvisible) != 0);
186        break;
187    case MACOSX_RSRCLENGTH_ATTRIBUTE:
188        *attributePtrPtr = Tcl_NewWideIntObj(*rsrcForkSize);
189        break;
190    }
191    return TCL_OK;
192#else
193    Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL);
194    return TCL_ERROR;
195#endif
196}
197
198/*
199 *---------------------------------------------------------------------------
200 *
201 * TclMacOSXSetFileAttribute --
202 *
203 *      Sets a MacOSX attribute of a file. Which attribute is controlled by
204 *      objIndex.
205 *
206 * Results:
207 *      Standard TCL result.
208 *
209 * Side effects:
210 *      As above.
211 *
212 *---------------------------------------------------------------------------
213 */
214
215int
216TclMacOSXSetFileAttribute(
217    Tcl_Interp *interp,         /* The interp for error reporting. */
218    int objIndex,               /* The index of the attribute. */
219    Tcl_Obj *fileName,          /* The name of the file (UTF-8). */
220    Tcl_Obj *attributePtr)      /* New owner for file. */
221{
222#ifdef HAVE_GETATTRLIST
223    int result;
224    Tcl_StatBuf statBuf;
225    struct attrlist alist;
226    fileinfobuf finfo;
227    finderinfo *finder = (finderinfo*)(&finfo.data);
228    off_t *rsrcForkSize = (off_t*)(&finfo.data);
229    const char *native;
230
231    result = TclpObjStat(fileName, &statBuf);
232
233    if (result != 0) {
234        Tcl_AppendResult(interp, "could not read \"",
235                TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
236        return TCL_ERROR;
237    }
238
239    if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) {
240        /*
241         * Directories only support attribute "-hidden".
242         */
243
244        errno = EISDIR;
245        Tcl_AppendResult(interp, "invalid attribute: ",
246                Tcl_PosixError(interp), NULL);
247        return TCL_ERROR;
248    }
249
250    bzero(&alist, sizeof(struct attrlist));
251    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
252    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
253        alist.fileattr = ATTR_FILE_RSRCLENGTH;
254    } else {
255        alist.commonattr = ATTR_CMN_FNDRINFO;
256    }
257    native = Tcl_FSGetNativePath(fileName);
258    result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);
259
260    if (result != 0) {
261        Tcl_AppendResult(interp, "could not read attributes of \"",
262                TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
263        return TCL_ERROR;
264    }
265
266    if (objIndex != MACOSX_RSRCLENGTH_ATTRIBUTE) {
267        OSType t;
268        int h;
269
270        switch (objIndex) {
271        case MACOSX_CREATOR_ATTRIBUTE:
272            if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) {
273                return TCL_ERROR;
274            }
275            finder->creator = OSSwapHostToBigInt32(t);
276            break;
277        case MACOSX_TYPE_ATTRIBUTE:
278            if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) {
279                return TCL_ERROR;
280            }
281            finder->type = OSSwapHostToBigInt32(t);
282            break;
283        case MACOSX_HIDDEN_ATTRIBUTE:
284            if (Tcl_GetBooleanFromObj(interp, attributePtr, &h) != TCL_OK) {
285                return TCL_ERROR;
286            }
287            if (h) {
288                finder->fdFlags |= kFinfoIsInvisible;
289            } else {
290                finder->fdFlags &= ~kFinfoIsInvisible;
291            }
292            break;
293        }
294
295        result = setattrlist(native, &alist,
296                &finfo.data, sizeof(finfo.data), 0);
297
298        if (result != 0) {
299            Tcl_AppendResult(interp, "could not set attributes of \"",
300                    TclGetString(fileName), "\": ",
301                    Tcl_PosixError(interp), NULL);
302            return TCL_ERROR;
303        }
304    } else {
305        Tcl_WideInt newRsrcForkSize;
306
307        if (Tcl_GetWideIntFromObj(interp, attributePtr,
308                &newRsrcForkSize) != TCL_OK) {
309            return TCL_ERROR;
310        }
311
312        if (newRsrcForkSize != *rsrcForkSize) {
313            Tcl_DString ds;
314
315            /*
316             * Only setting rsrclength to 0 to strip a file's resource fork is
317             * supported.
318             */
319
320            if(newRsrcForkSize != 0) {
321                Tcl_AppendResult(interp,
322                        "setting nonzero rsrclength not supported", NULL);
323                return TCL_ERROR;
324            }
325
326            /*
327             * Construct path to resource fork.
328             */
329
330            Tcl_DStringInit(&ds);
331            Tcl_DStringAppend(&ds, native, -1);
332            Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, -1);
333
334            result = truncate(Tcl_DStringValue(&ds), (off_t)0);
335            if (result != 0) {
336                /*
337                 * truncate() on a valid resource fork path may fail with
338                 * a permission error in some OS releases, try truncating
339                 * with open() instead:
340                 */
341                int fd = open(Tcl_DStringValue(&ds), O_WRONLY | O_TRUNC);
342                if (fd > 0) {
343                    result = close(fd);
344                }
345            }
346
347            Tcl_DStringFree(&ds);
348
349            if (result != 0) {
350                Tcl_AppendResult(interp,
351                        "could not truncate resource fork of \"",
352                        TclGetString(fileName), "\": ",
353                        Tcl_PosixError(interp), NULL);
354                return TCL_ERROR;
355            }
356        }
357    }
358    return TCL_OK;
359#else
360    Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL);
361    return TCL_ERROR;
362#endif
363}
364
365/*
366 *---------------------------------------------------------------------------
367 *
368 * TclMacOSXCopyFileAttributes --
369 *
370 *      Copy the MacOSX attributes and resource fork (if present) from one
371 *      file to another.
372 *
373 * Results:
374 *      Standard Tcl result.
375 *
376 * Side effects:
377 *      MacOSX attributes and resource fork are updated in the new file to
378 *      reflect the old file.
379 *
380 *---------------------------------------------------------------------------
381 */
382
383int
384TclMacOSXCopyFileAttributes(
385    CONST char *src,            /* Path name of source file (native). */
386    CONST char *dst,            /* Path name of target file (native). */
387    CONST Tcl_StatBuf *statBufPtr)
388                                /* Stat info for source file */
389{
390#ifdef WEAK_IMPORT_COPYFILE
391    if (copyfile != NULL) {
392#endif
393#ifdef HAVE_COPYFILE
394    if (copyfile(src, dst, NULL, COPYFILE_XATTR |
395            (S_ISLNK(statBufPtr->st_mode) ? COPYFILE_NOFOLLOW_SRC :
396                                            COPYFILE_ACL)) < 0) {
397        return TCL_ERROR;
398    }
399    return TCL_OK;
400#endif /* HAVE_COPYFILE */
401#ifdef WEAK_IMPORT_COPYFILE
402    } else {
403#endif
404#if !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)
405#ifdef HAVE_GETATTRLIST
406    struct attrlist alist;
407    fileinfobuf finfo;
408    off_t *rsrcForkSize = (off_t*)(&finfo.data);
409
410    bzero(&alist, sizeof(struct attrlist));
411    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
412    alist.commonattr = ATTR_CMN_FNDRINFO;
413
414    if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
415        return TCL_ERROR;
416    }
417
418    if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
419        return TCL_ERROR;
420    }
421
422    if (!S_ISDIR(statBufPtr->st_mode)) {
423        /*
424         * Only copy non-empty resource fork.
425         */
426
427        alist.commonattr = 0;
428        alist.fileattr = ATTR_FILE_RSRCLENGTH;
429
430        if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
431            return TCL_ERROR;
432        }
433
434        if(*rsrcForkSize > 0) {
435            int result;
436            Tcl_DString ds_src, ds_dst;
437
438            /*
439             * Construct paths to resource forks.
440             */
441
442            Tcl_DStringInit(&ds_src);
443            Tcl_DStringAppend(&ds_src, src, -1);
444            Tcl_DStringAppend(&ds_src, _PATH_RSRCFORKSPEC, -1);
445            Tcl_DStringInit(&ds_dst);
446            Tcl_DStringAppend(&ds_dst, dst, -1);
447            Tcl_DStringAppend(&ds_dst, _PATH_RSRCFORKSPEC, -1);
448
449            result = TclUnixCopyFile(Tcl_DStringValue(&ds_src),
450                    Tcl_DStringValue(&ds_dst), statBufPtr, 1);
451
452            Tcl_DStringFree(&ds_src);
453            Tcl_DStringFree(&ds_dst);
454
455            if (result != 0) {
456                return TCL_ERROR;
457            }
458        }
459    }
460    return TCL_OK;
461#else
462    return TCL_ERROR;
463#endif /* HAVE_GETATTRLIST */
464#endif /* !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) */
465#ifdef WEAK_IMPORT_COPYFILE
466    }
467#endif
468}
469
470/*
471 *----------------------------------------------------------------------
472 *
473 * TclMacOSXMatchType --
474 *
475 *      This routine is used by the globbing code to check if a file
476 *      matches a given mac type and/or creator code.
477 *
478 * Results:
479 *      The return value is 1, 0 or -1 indicating whether the file
480 *      matches the given criteria, does not match them, or an error
481 *      occurred (in wich case an error is left in interp).
482 *
483 * Side effects:
484 *      None.
485 *
486 *----------------------------------------------------------------------
487 */
488
489int
490TclMacOSXMatchType(
491    Tcl_Interp *interp,       /* Interpreter to receive errors. */
492    CONST char *pathName,     /* Native path to check. */
493    CONST char *fileName,     /* Native filename to check. */
494    Tcl_StatBuf *statBufPtr,  /* Stat info for file to check */
495    Tcl_GlobTypeData *types)  /* Type description to match against. */
496{
497#ifdef HAVE_GETATTRLIST
498    struct attrlist alist;
499    fileinfobuf finfo;
500    finderinfo *finder = (finderinfo*)(&finfo.data);
501    OSType osType;
502
503    bzero(&alist, sizeof(struct attrlist));
504    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
505    alist.commonattr = ATTR_CMN_FNDRINFO;
506    if (getattrlist(pathName, &alist, &finfo, sizeof(fileinfobuf), 0) != 0) {
507        return 0;
508    }
509    if ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
510            !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {
511        return 0;
512    }
513    if (S_ISDIR(statBufPtr->st_mode) && (types->macType || types->macCreator)) {
514        /* Directories don't support types or creators */
515        return 0;
516    }
517    if (types->macType) {
518        if (GetOSTypeFromObj(interp, types->macType, &osType) != TCL_OK) {
519            return -1;
520        }
521        if (osType != OSSwapBigToHostInt32(finder->type)) {
522            return 0;
523        }
524    }
525    if (types->macCreator) {
526        if (GetOSTypeFromObj(interp, types->macCreator, &osType) != TCL_OK) {
527            return -1;
528        }
529        if (osType != OSSwapBigToHostInt32(finder->creator)) {
530            return 0;
531        }
532    }
533#endif
534    return 1;
535}
536
537/*
538 *----------------------------------------------------------------------
539 *
540 * GetOSTypeFromObj --
541 *
542 *      Attempt to return an OSType from the Tcl object "objPtr".
543 *
544 * Results:
545 *      Standard TCL result. If an error occurs during conversion, an error
546 *      message is left in interp->objResult.
547 *
548 * Side effects:
549 *      The string representation of objPtr will be updated if necessary.
550 *
551 *----------------------------------------------------------------------
552 */
553
554static int
555GetOSTypeFromObj(
556    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
557    Tcl_Obj *objPtr,            /* The object from which to get an OSType. */
558    OSType *osTypePtr)          /* Place to store resulting OSType. */
559{
560    int result = TCL_OK;
561
562    if (objPtr->typePtr != &tclOSTypeType) {
563        result = tclOSTypeType.setFromAnyProc(interp, objPtr);
564    };
565    *osTypePtr = (OSType) objPtr->internalRep.longValue;
566    return result;
567}
568
569/*
570 *----------------------------------------------------------------------
571 *
572 * NewOSTypeObj --
573 *
574 *      Create a new OSType object.
575 *
576 * Results:
577 *      The newly created OSType object is returned, it has ref count 0.
578 *
579 * Side effects:
580 *      None.
581 *
582 *----------------------------------------------------------------------
583 */
584
585static Tcl_Obj *
586NewOSTypeObj(
587    const OSType osType)    /* OSType used to initialize the new object. */
588{
589    Tcl_Obj *objPtr;
590
591    TclNewObj(objPtr);
592    Tcl_InvalidateStringRep(objPtr);
593    objPtr->internalRep.longValue = (long) osType;
594    objPtr->typePtr = &tclOSTypeType;
595    return objPtr;
596}
597
598/*
599 *----------------------------------------------------------------------
600 *
601 * SetOSTypeFromAny --
602 *
603 *      Attempts to force the internal representation for a Tcl object to
604 *      tclOSTypeType, specifically.
605 *
606 * Results:
607 *      The return value is a standard object Tcl result. If an error occurs
608 *      during conversion, an error message is left in the interpreter's
609 *      result unless "interp" is NULL.
610 *
611 *----------------------------------------------------------------------
612 */
613
614static int
615SetOSTypeFromAny(
616    Tcl_Interp *interp,         /* Tcl interpreter */
617    Tcl_Obj *objPtr)            /* Pointer to the object to convert */
618{
619    char *string;
620    int length, result = TCL_OK;
621    Tcl_DString ds;
622    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
623
624    string = Tcl_GetStringFromObj(objPtr, &length);
625    Tcl_UtfToExternalDString(encoding, string, length, &ds);
626
627    if (Tcl_DStringLength(&ds) > 4) {
628        Tcl_AppendResult(interp, "expected Macintosh OS type but got \"",
629                string, "\": ", NULL);
630        result = TCL_ERROR;
631    } else {
632        OSType osType;
633        char string[4] = {'\0','\0','\0','\0'};
634        memcpy(string, Tcl_DStringValue(&ds),
635                (size_t) Tcl_DStringLength(&ds));
636        osType = (OSType) string[0] << 24 |
637                 (OSType) string[1] << 16 |
638                 (OSType) string[2] <<  8 |
639                 (OSType) string[3];
640        TclFreeIntRep(objPtr);
641        objPtr->internalRep.longValue = (long) osType;
642        objPtr->typePtr = &tclOSTypeType;
643    }
644    Tcl_DStringFree(&ds);
645    Tcl_FreeEncoding(encoding);
646    return result;
647}
648
649/*
650 *----------------------------------------------------------------------
651 *
652 * UpdateStringOfOSType --
653 *
654 *      Update the string representation for an OSType object. Note: This
655 *      function does not free an existing old string rep so storage will be
656 *      lost if this has not already been done.
657 *
658 * Results:
659 *      None.
660 *
661 * Side effects:
662 *      The object's string is set to a valid string that results from the
663 *      OSType-to-string conversion.
664 *
665 *----------------------------------------------------------------------
666 */
667
668static void
669UpdateStringOfOSType(
670    register Tcl_Obj *objPtr)   /* OSType object whose string rep to update. */
671{
672    char string[5];
673    OSType osType = (OSType) objPtr->internalRep.longValue;
674    Tcl_DString ds;
675    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
676
677    string[0] = (char) (osType >> 24);
678    string[1] = (char) (osType >> 16);
679    string[2] = (char) (osType >>  8);
680    string[3] = (char) (osType);
681    string[4] = '\0';
682    Tcl_ExternalToUtfDString(encoding, string, -1, &ds);
683    objPtr->bytes = ckalloc((unsigned) Tcl_DStringLength(&ds) + 1);
684    strcpy(objPtr->bytes, Tcl_DStringValue(&ds));
685    objPtr->length = Tcl_DStringLength(&ds);
686    Tcl_DStringFree(&ds);
687    Tcl_FreeEncoding(encoding);
688}
689
690/*
691 * Local Variables:
692 * mode: c
693 * c-basic-offset: 4
694 * fill-column: 78
695 * End:
696 */
Note: See TracBrowser for help on using the repository browser.