Print this page
3819 zfs receive can fail due to processing order


 706 
 707         if (zhp->zfs_dmustats.dds_origin[0]) {
 708                 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
 709                     zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
 710                 if (origin == NULL)
 711                         return (-1);
 712                 VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
 713                     origin->zfs_dmustats.dds_guid));
 714         }
 715 
 716         /* iterate over props */
 717         VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
 718         send_iterate_prop(zhp, nv);
 719         VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
 720         nvlist_free(nv);
 721 
 722         /* iterate over snaps, and set sd->parent_fromsnap_guid */
 723         sd->parent_fromsnap_guid = 0;
 724         VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
 725         VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
 726         (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
 727         VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
 728         VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
 729         nvlist_free(sd->parent_snaps);
 730         nvlist_free(sd->snapprops);
 731 
 732         /* add this fs to nvlist */
 733         (void) snprintf(guidstring, sizeof (guidstring),
 734             "0x%llx", (longlong_t)guid);
 735         VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
 736         nvlist_free(nvfs);
 737 
 738         /* iterate over children */
 739         if (sd->recursive)
 740                 rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
 741 
 742         sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
 743 
 744         zfs_close(zhp);
 745         return (rv);
 746 }


1919         create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
1920 
1921         if (create1 < create2)
1922                 rv = -1;
1923         else if (create1 > create2)
1924                 rv = +1;
1925         else
1926                 rv = 0;
1927 
1928         zfs_close(guid1hdl);
1929         zfs_close(guid2hdl);
1930 
1931         return (rv);
1932 }
1933 
1934 static int
1935 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1936     recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
1937     nvlist_t *renamed)
1938 {
1939         nvlist_t *local_nv;
1940         avl_tree_t *local_avl;
1941         nvpair_t *fselem, *nextfselem;
1942         char *fromsnap;
1943         char newname[ZFS_MAXNAMELEN];
1944         int error;
1945         boolean_t needagain, progress, recursive;
1946         char *s1, *s2;
1947 
1948         VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1949 
1950         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
1951             ENOENT);
1952 
1953         if (flags->dryrun)
1954                 return (0);
1955 
1956 again:
1957         needagain = progress = B_FALSE;
1958 
1959         if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1960             recursive, &local_nv, &local_avl)) != 0)
1961                 return (error);
1962 


1963         /*
1964          * Process deletes and renames
1965          */
1966         for (fselem = nvlist_next_nvpair(local_nv, NULL);
1967             fselem; fselem = nextfselem) {
1968                 nvlist_t *nvfs, *snaps;
1969                 nvlist_t *stream_nvfs = NULL;
1970                 nvpair_t *snapelem, *nextsnapelem;
1971                 uint64_t fromguid = 0;
1972                 uint64_t originguid = 0;
1973                 uint64_t stream_originguid = 0;
1974                 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1975                 char *fsname, *stream_fsname;
1976 
1977                 nextfselem = nvlist_next_nvpair(local_nv, fselem);
1978 
1979                 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1980                 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1981                 VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1982                 VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",


2014                                         (void) printf("promoting %s\n", fsname);
2015 
2016                                 origin_nvfs = fsavl_find(local_avl, originguid,
2017                                     NULL);
2018                                 VERIFY(0 == nvlist_lookup_string(origin_nvfs,
2019                                     "name", &origin_fsname));
2020                                 (void) strlcpy(zc.zc_value, origin_fsname,
2021                                     sizeof (zc.zc_value));
2022                                 (void) strlcpy(zc.zc_name, fsname,
2023                                     sizeof (zc.zc_name));
2024                                 error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
2025                                 if (error == 0)
2026                                         progress = B_TRUE;
2027                                 break;
2028                         }
2029                         default:
2030                                 break;
2031                         case -1:
2032                                 fsavl_destroy(local_avl);
2033                                 nvlist_free(local_nv);

2034                                 return (-1);
2035                         }
2036                         /*
2037                          * We had/have the wrong origin, therefore our
2038                          * list of snapshots is wrong.  Need to handle
2039                          * them on the next pass.
2040                          */
2041                         needagain = B_TRUE;
2042                         continue;
2043                 }
2044 
2045                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
2046                     snapelem; snapelem = nextsnapelem) {
2047                         uint64_t thisguid;
2048                         char *stream_snapname;
2049                         nvlist_t *found, *props;
2050 
2051                         nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
2052 
2053                         VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2054                         found = fsavl_find(stream_avl, thisguid,
2055                             &stream_snapname);
2056 
2057                         /* check for delete */
2058                         if (found == NULL) {
2059                                 char name[ZFS_MAXNAMELEN];
2060 
2061                                 if (!flags->force)
2062                                         continue;
2063 
2064                                 (void) snprintf(name, sizeof (name), "%s@%s",
2065                                     fsname, nvpair_name(snapelem));
2066 
2067                                 error = recv_destroy(hdl, name,
2068                                     strlen(fsname)+1, newname, flags);
2069                                 if (error)
2070                                         needagain = B_TRUE;
2071                                 else
2072                                         progress = B_TRUE;



2073                                 continue;
2074                         }
2075 
2076                         stream_nvfs = found;
2077 
2078                         if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
2079                             &props) && 0 == nvlist_lookup_nvlist(props,
2080                             stream_snapname, &props)) {
2081                                 zfs_cmd_t zc = { 0 };
2082 
2083                                 zc.zc_cookie = B_TRUE; /* received */
2084                                 (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
2085                                     "%s@%s", fsname, nvpair_name(snapelem));
2086                                 if (zcmd_write_src_nvlist(hdl, &zc,
2087                                     props) == 0) {
2088                                         (void) zfs_ioctl(hdl,
2089                                             ZFS_IOC_SET_PROP, &zc);
2090                                         zcmd_free_nvlists(&zc);
2091                                 }
2092                         }


2108                                         needagain = B_TRUE;
2109                                 else
2110                                         progress = B_TRUE;
2111                         }
2112 
2113                         if (strcmp(stream_snapname, fromsnap) == 0)
2114                                 fromguid = thisguid;
2115                 }
2116 
2117                 /* check for delete */
2118                 if (stream_nvfs == NULL) {
2119                         if (!flags->force)
2120                                 continue;
2121 
2122                         error = recv_destroy(hdl, fsname, strlen(tofs)+1,
2123                             newname, flags);
2124                         if (error)
2125                                 needagain = B_TRUE;
2126                         else
2127                                 progress = B_TRUE;



2128                         continue;
2129                 }
2130 
2131                 if (fromguid == 0) {
2132                         if (flags->verbose) {
2133                                 (void) printf("local fs %s does not have "
2134                                     "fromsnap (%s in stream); must have "
2135                                     "been deleted locally; ignoring\n",
2136                                     fsname, fromsnap);
2137                         }
2138                         continue;
2139                 }
2140 
2141                 VERIFY(0 == nvlist_lookup_string(stream_nvfs,
2142                     "name", &stream_fsname));
2143                 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
2144                     "parentfromsnap", &stream_parent_fromsnap_guid));
2145 
2146                 s1 = strrchr(fsname, '/');
2147                 s2 = strrchr(stream_fsname, '/');
2148 
2149                 /*


















2150                  * Check for rename. If the exact receive path is specified, it
2151                  * does not count as a rename, but we still need to check the
2152                  * datasets beneath it.
2153                  */
2154                 if ((stream_parent_fromsnap_guid != 0 &&
2155                     parent_fromsnap_guid != 0 &&
2156                     stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
2157                     ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
2158                     (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
2159                         nvlist_t *parent;
2160                         char tryname[ZFS_MAXNAMELEN];
2161 
2162                         parent = fsavl_find(local_avl,
2163                             stream_parent_fromsnap_guid, NULL);
2164                         /*
2165                          * NB: parent might not be found if we used the
2166                          * tosnap for stream_parent_fromsnap_guid,
2167                          * because the parent is a newly-created fs;
2168                          * we'll be able to rename it after we recv the
2169                          * new fs.


2183                                 }
2184                         }
2185 
2186                         newname[0] = '\0';
2187 
2188                         error = recv_rename(hdl, fsname, tryname,
2189                             strlen(tofs)+1, newname, flags);
2190 
2191                         if (renamed != NULL && newname[0] != '\0') {
2192                                 VERIFY(0 == nvlist_add_boolean(renamed,
2193                                     newname));
2194                         }
2195 
2196                         if (error)
2197                                 needagain = B_TRUE;
2198                         else
2199                                 progress = B_TRUE;
2200                 }
2201         }
2202 

2203         fsavl_destroy(local_avl);
2204         nvlist_free(local_nv);

2205 
2206         if (needagain && progress) {
2207                 /* do another pass to fix up temporary names */
2208                 if (flags->verbose)
2209                         (void) printf("another pass:\n");
2210                 goto again;
2211         }
2212 
2213         return (needagain);
2214 }
2215 
2216 static int
2217 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2218     recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2219     char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2220 {
2221         nvlist_t *stream_nv = NULL;
2222         avl_tree_t *stream_avl = NULL;
2223         char *fromsnap = NULL;
2224         char *cp;




 706 
 707         if (zhp->zfs_dmustats.dds_origin[0]) {
 708                 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
 709                     zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
 710                 if (origin == NULL)
 711                         return (-1);
 712                 VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
 713                     origin->zfs_dmustats.dds_guid));
 714         }
 715 
 716         /* iterate over props */
 717         VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
 718         send_iterate_prop(zhp, nv);
 719         VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
 720         nvlist_free(nv);
 721 
 722         /* iterate over snaps, and set sd->parent_fromsnap_guid */
 723         sd->parent_fromsnap_guid = 0;
 724         VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
 725         VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
 726         (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd);
 727         VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
 728         VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
 729         nvlist_free(sd->parent_snaps);
 730         nvlist_free(sd->snapprops);
 731 
 732         /* add this fs to nvlist */
 733         (void) snprintf(guidstring, sizeof (guidstring),
 734             "0x%llx", (longlong_t)guid);
 735         VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
 736         nvlist_free(nvfs);
 737 
 738         /* iterate over children */
 739         if (sd->recursive)
 740                 rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
 741 
 742         sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
 743 
 744         zfs_close(zhp);
 745         return (rv);
 746 }


1919         create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
1920 
1921         if (create1 < create2)
1922                 rv = -1;
1923         else if (create1 > create2)
1924                 rv = +1;
1925         else
1926                 rv = 0;
1927 
1928         zfs_close(guid1hdl);
1929         zfs_close(guid2hdl);
1930 
1931         return (rv);
1932 }
1933 
1934 static int
1935 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1936     recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
1937     nvlist_t *renamed)
1938 {
1939         nvlist_t *local_nv, *deleted = NULL;
1940         avl_tree_t *local_avl;
1941         nvpair_t *fselem, *nextfselem;
1942         char *fromsnap;
1943         char newname[ZFS_MAXNAMELEN], guidname[32];
1944         int error;
1945         boolean_t needagain, progress, recursive;
1946         char *s1, *s2;
1947 
1948         VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1949 
1950         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
1951             ENOENT);
1952 
1953         if (flags->dryrun)
1954                 return (0);
1955 
1956 again:
1957         needagain = progress = B_FALSE;
1958 
1959         if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1960             recursive, &local_nv, &local_avl)) != 0)
1961                 return (error);
1962 
1963         deleted = fnvlist_alloc();
1964 
1965         /*
1966          * Process deletes and renames
1967          */
1968         for (fselem = nvlist_next_nvpair(local_nv, NULL);
1969             fselem; fselem = nextfselem) {
1970                 nvlist_t *nvfs, *snaps;
1971                 nvlist_t *stream_nvfs = NULL;
1972                 nvpair_t *snapelem, *nextsnapelem;
1973                 uint64_t fromguid = 0;
1974                 uint64_t originguid = 0;
1975                 uint64_t stream_originguid = 0;
1976                 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1977                 char *fsname, *stream_fsname;
1978 
1979                 nextfselem = nvlist_next_nvpair(local_nv, fselem);
1980 
1981                 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1982                 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1983                 VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1984                 VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",


2016                                         (void) printf("promoting %s\n", fsname);
2017 
2018                                 origin_nvfs = fsavl_find(local_avl, originguid,
2019                                     NULL);
2020                                 VERIFY(0 == nvlist_lookup_string(origin_nvfs,
2021                                     "name", &origin_fsname));
2022                                 (void) strlcpy(zc.zc_value, origin_fsname,
2023                                     sizeof (zc.zc_value));
2024                                 (void) strlcpy(zc.zc_name, fsname,
2025                                     sizeof (zc.zc_name));
2026                                 error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
2027                                 if (error == 0)
2028                                         progress = B_TRUE;
2029                                 break;
2030                         }
2031                         default:
2032                                 break;
2033                         case -1:
2034                                 fsavl_destroy(local_avl);
2035                                 nvlist_free(local_nv);
2036                                 nvlist_free(deleted);
2037                                 return (-1);
2038                         }
2039                         /*
2040                          * We had/have the wrong origin, therefore our
2041                          * list of snapshots is wrong.  Need to handle
2042                          * them on the next pass.
2043                          */
2044                         needagain = B_TRUE;
2045                         continue;
2046                 }
2047 
2048                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
2049                     snapelem; snapelem = nextsnapelem) {
2050                         uint64_t thisguid;
2051                         char *stream_snapname;
2052                         nvlist_t *found, *props;
2053 
2054                         nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
2055 
2056                         VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2057                         found = fsavl_find(stream_avl, thisguid,
2058                             &stream_snapname);
2059 
2060                         /* check for delete */
2061                         if (found == NULL) {
2062                                 char name[ZFS_MAXNAMELEN];
2063 
2064                                 if (!flags->force)
2065                                         continue;
2066 
2067                                 (void) snprintf(name, sizeof (name), "%s@%s",
2068                                     fsname, nvpair_name(snapelem));
2069 
2070                                 error = recv_destroy(hdl, name,
2071                                     strlen(fsname)+1, newname, flags);
2072                                 if (error)
2073                                         needagain = B_TRUE;
2074                                 else
2075                                         progress = B_TRUE;
2076                                 (void) sprintf(guidname, "%llu",
2077                                     (u_longlong_t)thisguid);
2078                                 fnvlist_add_boolean(deleted, guidname);
2079                                 continue;
2080                         }
2081 
2082                         stream_nvfs = found;
2083 
2084                         if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
2085                             &props) && 0 == nvlist_lookup_nvlist(props,
2086                             stream_snapname, &props)) {
2087                                 zfs_cmd_t zc = { 0 };
2088 
2089                                 zc.zc_cookie = B_TRUE; /* received */
2090                                 (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
2091                                     "%s@%s", fsname, nvpair_name(snapelem));
2092                                 if (zcmd_write_src_nvlist(hdl, &zc,
2093                                     props) == 0) {
2094                                         (void) zfs_ioctl(hdl,
2095                                             ZFS_IOC_SET_PROP, &zc);
2096                                         zcmd_free_nvlists(&zc);
2097                                 }
2098                         }


2114                                         needagain = B_TRUE;
2115                                 else
2116                                         progress = B_TRUE;
2117                         }
2118 
2119                         if (strcmp(stream_snapname, fromsnap) == 0)
2120                                 fromguid = thisguid;
2121                 }
2122 
2123                 /* check for delete */
2124                 if (stream_nvfs == NULL) {
2125                         if (!flags->force)
2126                                 continue;
2127 
2128                         error = recv_destroy(hdl, fsname, strlen(tofs)+1,
2129                             newname, flags);
2130                         if (error)
2131                                 needagain = B_TRUE;
2132                         else
2133                                 progress = B_TRUE;
2134                         (void) sprintf(guidname, "%llu",
2135                             (u_longlong_t)parent_fromsnap_guid);
2136                         fnvlist_add_boolean(deleted, guidname);
2137                         continue;
2138                 }
2139 
2140                 if (fromguid == 0) {
2141                         if (flags->verbose) {
2142                                 (void) printf("local fs %s does not have "
2143                                     "fromsnap (%s in stream); must have "
2144                                     "been deleted locally; ignoring\n",
2145                                     fsname, fromsnap);
2146                         }
2147                         continue;
2148                 }
2149 
2150                 VERIFY(0 == nvlist_lookup_string(stream_nvfs,
2151                     "name", &stream_fsname));
2152                 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
2153                     "parentfromsnap", &stream_parent_fromsnap_guid));
2154 
2155                 s1 = strrchr(fsname, '/');
2156                 s2 = strrchr(stream_fsname, '/');
2157 
2158                 /*
2159                  * Check if we're going to rename based on parent guid change
2160                  * and the current parent guid was also deleted. If it was then
2161                  * the rename will fail so avoid this and force an early retry
2162                  * to determine the new parent_fromsnap_guid.
2163                  */
2164                 if (stream_parent_fromsnap_guid != 0 &&
2165                     parent_fromsnap_guid != 0 &&
2166                     stream_parent_fromsnap_guid != parent_fromsnap_guid) {
2167                         (void) sprintf(guidname, "%llu",
2168                             (u_longlong_t)parent_fromsnap_guid);
2169                         if (nvlist_exists(deleted, guidname)) {
2170                                 progress = B_TRUE;
2171                                 needagain = B_TRUE;
2172                                 goto doagain;
2173                         }
2174                 }
2175 
2176                 /*
2177                  * Check for rename. If the exact receive path is specified, it
2178                  * does not count as a rename, but we still need to check the
2179                  * datasets beneath it.
2180                  */
2181                 if ((stream_parent_fromsnap_guid != 0 &&
2182                     parent_fromsnap_guid != 0 &&
2183                     stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
2184                     ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
2185                     (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
2186                         nvlist_t *parent;
2187                         char tryname[ZFS_MAXNAMELEN];
2188 
2189                         parent = fsavl_find(local_avl,
2190                             stream_parent_fromsnap_guid, NULL);
2191                         /*
2192                          * NB: parent might not be found if we used the
2193                          * tosnap for stream_parent_fromsnap_guid,
2194                          * because the parent is a newly-created fs;
2195                          * we'll be able to rename it after we recv the
2196                          * new fs.


2210                                 }
2211                         }
2212 
2213                         newname[0] = '\0';
2214 
2215                         error = recv_rename(hdl, fsname, tryname,
2216                             strlen(tofs)+1, newname, flags);
2217 
2218                         if (renamed != NULL && newname[0] != '\0') {
2219                                 VERIFY(0 == nvlist_add_boolean(renamed,
2220                                     newname));
2221                         }
2222 
2223                         if (error)
2224                                 needagain = B_TRUE;
2225                         else
2226                                 progress = B_TRUE;
2227                 }
2228         }
2229 
2230 doagain:
2231         fsavl_destroy(local_avl);
2232         nvlist_free(local_nv);
2233         nvlist_free(deleted);
2234 
2235         if (needagain && progress) {
2236                 /* do another pass to fix up temporary names */
2237                 if (flags->verbose)
2238                         (void) printf("another pass:\n");
2239                 goto again;
2240         }
2241 
2242         return (needagain);
2243 }
2244 
2245 static int
2246 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2247     recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2248     char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2249 {
2250         nvlist_t *stream_nv = NULL;
2251         avl_tree_t *stream_avl = NULL;
2252         char *fromsnap = NULL;
2253         char *cp;